简体   繁体   English

为什么我的所有对话屏幕同时显示? - ReactJS

[英]why are all my dialog screens showing at the same time? - ReactJS

first of all sorry if my question is unclear, it's my first time here (I just started learning web development four months ago haha).首先很抱歉,如果我的问题不清楚,这是我第一次来这里(我四个月前才开始学习网络开发哈哈)。

Chronology: I'm making note-like web.年表:我正在制作类似笔记的网页。 Each note have edit and delete button, what i want is when i press edit button or delete button, one edit form or alert will be displayed and change will be applied to the specific note.每个笔记都有编辑和删除按钮,我想要的是当我按下编辑按钮或删除按钮时,将显示一个编辑表单或警报,并将更改应用于特定笔记。 The problem is, when i pressed edit button on one of my note, all dialog screen for all notes are being displayed and stacked like this: All dialog screen are being displayed and stacked问题是,当我在我的一个笔记上按下编辑按钮时,所有笔记的所有对话框屏幕都像这样显示和堆叠: All dialog screen are being displayed and stacked

Anyone know why and how to fix it?任何人都知道为什么以及如何解决它?

Here is the code (edited):这是代码(已编辑):

const [notes, setNotes] = useState([]);
const [title, setTitle] = useState('');
const [text, setText] = useState('');
const [newTitle, setNewTitle] = useState('');
const [newText, setNewText] = useState('');
const [open, setOpen] = useState(false);
const [openAlert, setOpenAlert] = useState(false);
const [openEdit, setOpenEdit] = useState(false);
const newNote = () => {
    Axios.post('http://localhost:8888/new', {
        title: title,
        text: text
    }).then((response) => {
        setNotes([...notes, response.data])
    })
};
const dataNotes = () => {
    Axios.get('http://localhost:8888/')
        .then((response) => {
            setNotes(response.data)
        })
};
const deleteNote = (id) => {
    Axios.delete(`http://localhost:8888/${id}`)
        .then((response) => {
            setNotes(notes.filter(note => note._id !== id))
        })
};
const editNote = (id) => {
    Axios.patch(`http://localhost:8888/${id}`, {
        title: newTitle,
        text: newText
    }).then((response) => {
        const newNotes = notes.map(note => {
            if (note._id === `${id}`) {
                return { ...note, title: newTitle, text: newText }
            }
            return note
        });
        setNotes(newNotes)
    })
}
const handleClickOpen = () => {
    setOpen(true);
};
const handleClose = () => {
    setOpen(false);
};
const handleClickOpenAlert = () => {
    setOpenAlert(true);
};
const handleCloseAlert = () => {
    setOpenAlert(false);
};
const handleClickOpenEdit = () => {
    setOpenEdit(true)
};
const handleCloseEdit = () => {
    setOpenEdit(false);
};
useEffect(() => {
    dataNotes();
}, []);
<section className='notes'>
    {notes.map((note) => (
        <div className="note-container" key={note._id}>
            <h3>
                {note.title}
            </h3>
            <p>
                {note.text}
            </p>
            <section className="tool-container">
                <img
                    src={PencilIcon}
                    alt='edit'
                    className="pencil"
                    onClick={handleClickOpenEdit}
                />
                <img
                    src={TrashIcon}
                    alt='delete'
                    className="trash"
                    onClick={handleClickOpenAlert}
                />
                <Dialog open={openAlert} onClose={handleCloseAlert} aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description">
                    <DialogTitle id='alert-dialog-title'>{'Are you sure want to delete this note?'}</DialogTitle>
                    <DialogContent>
                        <DialogContentText id='alert-dialog-description'>
                            Once you delete this note, you can't get it back
                        </DialogContentText>
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={handleCloseAlert}>Cancel</Button>
                        <Button onClick={(event) => {
                            deleteNote(note._id);
                            handleCloseAlert();
                        }}>Delete</Button>
                    </DialogActions>
                </Dialog>
                <Dialog open={openEdit} onClose={handleCloseEdit}>
                    <DialogTitle>Edit note</DialogTitle>
                    <DialogContent>
                        <TextField autoFocus type='text' id='new-title' label='New Note Title' fullWidth variant='standard' defaultValue={note.title} required onChange={(evt) => {
                            if (evt.target.value !== null) {
                                setNewTitle(evt.target.value)
                            } else {
                                setNewTitle(note.title)
                            }
                        }} />
                        <TextField type='text' id='new-text' label='New Note Text' fullWidth variant='standard' multiline defaultValue={note.text} required onChange={(evt) => {
                            if (evt.target.value !== null) {
                                setNewText(evt.target.value)
                            } else {
                                setNewText(note.text)
                            }
                        }} />
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={handleCloseEdit}>Cancel</Button>
                        <Button onClick={() => {
                            editNote(note._id);
                            handleCloseEdit();
                        }}>Edit Note</Button>
                    </DialogActions>
                </Dialog>
            </section>
        </div>
    ))}
</section>

I think i'm missing something trivial here, but i don't know what it is.我想我在这里遗漏了一些微不足道的东西,但我不知道它是什么。

All your notes are sharing the same "open" state您所有的笔记都共享相同的“打开”状态

This is why opening one note, opens them all.这就是为什么打开一个音符,打开所有音符。

const [openAlert, setOpenAlert] = useState(false);
const [openEdit, setOpenEdit] = useState(false);

I am not familiar with ReactJS but I am wondering whether something along these lines is possible.我不熟悉 ReactJS,但我想知道这些方面的东西是否可行。 Instead of storing a single boolean in the state, store an object with an entry for each note.不是在状态中存储单个布尔值,而是存储一个对象,每个音符都有一个条目。 The keys in the object can be the note Ids.对象中的键可以是笔记 ID。 For simplicity you can also say that if a key is absent, the state is false.为简单起见,您也可以说如果没有密钥,则状态为假。 That way you can initialise with just an empty object.这样你就可以只用一个空对象进行初始化。

const [openAlert, setOpenAlert] = useState({});
const [openEdit, setOpenEdit] = useState({});

Then your handler functions can be of this form:那么你的处理函数可以是这种形式:

const handleClickOpenEdit = (id) => {
  setOpenEdit(oldState => {
      ... oldState,
      [id]:true
  });
};

This means, when you click Open for Edit, expect to be passed the Id of the note, and the process of opening is as follows:也就是说,当你点击Open for Edit时,期望传递的是笔记的Id,打开过程如下:

  1. Start with the old contents of the state variable.从状态变量的旧内容开始。
  2. Add an entry (or replace it if it already exists) for the note Id, saying true .为笔记 Id 添加一个条目(如果它已经存在,则替换它),说true
  3. Return that as the new contents of the state variable.将其作为状态变量的新内容返回。

You would call this handler with the note Id:您可以使用注释 ID 调用此处理程序:

            <img
                src={PencilIcon}
                alt='edit'
                className="pencil"
                onClick={handleClickOpenEdit(note._id)}
            />
           

Issue: All dialogs are using a single state.问题:所有对话框都使用单一状态。

Solution:解决方案:
Make a seperate component for DialogBox为 DialogBox 制作一个单独的组件

function DialogBox({note,title,content}) { 

   const [openAlert, setOpenAlert] = useState(false);
   const [openEdit, setOpenEdit] = useState(false);

   const handleClickOpenAlert = () => {
      setOpenAlert(true);
    }; 
   const handleCloseAlert = () => {
      setOpenAlert(false);
   };
   const handleClickOpenEdit = () => {
      setOpenEdit(true);
   };
   const handleCloseEdit = () => {
      setOpenEdit(false);
   }

    return (
        <Dialog open={openEdit} onClose={handleCloseEdit}>
            <DialogTitle>{title}</DialogTitle>
                <DialogContent>
                     {content}
                </DialogContent>
                <DialogActions>
                    <Button onClick={handleCloseEdit}>Cancel</Button>
                    <Button onClick={() => {
                            editNote(note._id);
                            handleCloseEdit();
                           }}>Edit Note</Button>
                </DialogActions>
          </Dialog>
    );
}
export default DialogBox;

Use that component in main component在主组件中使用该组件

<section className='notes'>
    {notes.map((note) => (
        <div className="note-container" key={note._id}>
            <h3>
                {note.title}
            </h3>
            <p>
                {note.text}
            </p>
            <section className="tool-container">
                <img
                    src={PencilIcon}
                    alt='edit'
                    className="pencil"
                    onClick={handleClickOpenEdit}
                />
                <img
                    src={TrashIcon}
                    alt='delete'
                    className="trash"
                    onClick={handleClickOpenAlert}
                />
                <DialogBox 
                   title={"Are you sure want to delete this note?"}
                   content={"Once you delete this note, you can't get it back"}
                   note={note}
                />
                <DialogBox 
                   title={"Edit Note"}
                   content={<EditComponent/>}
                   note={note}
                />
</section>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM