reactjs 为什么这段代码中的useState不更新id(文本更新了但id没有更新)?

vdgimpew  于 2022-12-03  发布在  React
关注(0)|答案(2)|浏览(137)

我尝试使用useState挂接增加ID值,但它没有增加。我必须调用fct两次才能增加ID。我可以通过控制台日志查看useState前后的对象,但结果相同

function ToDoListApp() {
    const [noteList, setNoteList]=useState([])
    const [note,setNote]=useState({ noteId: 0 , txt: "", noteState: false })
    function addToList(e) {
        e.preventDefault();
        if(noteList.length===0){
            console.log(note)
            setNote({noteId: 0 , txt: note.txt ,noteState: false })
            setNoteList(noteList=>[...noteList,note])
        }else{
            console.log(note)
            console.log(noteList[noteList.length-1].noteId + 1)
            setNote({noteId:noteList[noteList.length-1].noteId + 1,txt:note.txt, noteState:false})
            setNoteList(noteList=>[...noteList,note])
            console.log(note)
            
        }
          
    }
    function deleteItemFromList(e,id){
        
        setNoteList(noteList.filter(note => note.noteId !== id ))
        console.log(noteList.length)
    }
    function handleTheNoteTxt(e) {
        e.preventDefault();
        setNote({
            ...note,
            txt:e.target.value
        })
        
      }

    const notesDiplay =noteList.map((note)=>
    <Stack key={note.noteId} direction="row" className="note-styling" justifyContent="center" alignItems="center" spacing={2}>
        <p>{note.txt} </p>
        <p>{note.noteId} </p>
        
        <Button onClick={e => deleteItemFromList(e,note.noteId)} variant="outlined" size='small' >X</Button>
        
    </Stack>
    )
  return (
    <div>
        <Stack direction="column" justifyContent="center" alignItems="center">
        <Stack className='note-app-container bg1' direction="column" justifyContent="flex-start" alignItems="center" spacing={2} >
            <div className='notes-input bg3'>
                <TextField autoFocus  label="Add your note" variant="standard" value={note.txt} 
                    onChange={handleTheNoteTxt}/>
                <Button variant="outlined" size='medium' onClick={addToList}>Add</Button>
            </div>
            <div className='notes-container bg3'>
            {notesDiplay}
            </div>
        </Stack>
        </Stack>     
    </div>
  )
}

export default ToDoListApp`
cbjzeqam

cbjzeqam1#

这里是一个修正的版本,有一点简化和重构。

import { useState } from 'react';
import { Stack, Button, TextField } from '@mui/material'

function ToDoListApp() {
    const [noteList, setNoteList] = useState([]);
    const [nextId, setNextId] = useState(1);
    const [value, setValue] = useState("")

    function addToList(e) {
        e.preventDefault();
        noteList.push({
            noteId: nextId,
            txt:  value,
            noteState: false
        })
        setNextId(val => val + 1);
        setValue("");
    }

    function deleteItemFromList(e, id) {

        setNoteList(noteList.filter(note => note.noteId !== id))
        console.log(noteList.length)
    }

    const notesDiplay = noteList.map((note) =>
        <Stack key={note.noteId} direction="row" className="note-styling" justifyContent="center" alignItems="center" spacing={2}>
            <p>{note.txt} </p>
            <p>{note.noteId} </p>
            <Button onClick={e => deleteItemFromList(e, note.noteId)} variant="outlined" size='small' >
                X
            </Button>
        </Stack>
    )

    return (
        <div>
            <Stack direction="column" justifyContent="center" alignItems="center">
                <Stack className='note-app-container bg1' direction="column" justifyContent="flex-start" alignItems="center" spacing={2} >
                    <div className='notes-input bg3'>
                        <TextField autoFocus label="Add your note" variant="standard"
                            onChange={(e) => setValue(e.target.value) } />
                        <Button variant="outlined" size='medium' onClick={addToList}>Add</Button>
                    </div>
                    <div className='notes-container bg3'>
                        {notesDiplay}
                    </div>
                </Stack>
            </Stack>
        </div>
    )
}

export default ToDoListApp

[EDIT- 附加推理信息]
1.来自@ChristianFritz的注解涵盖了您的实际bug -当您使用useState更新时,新值实际上并没有反映在下面的代码行中。我在这里使用nextId状态变量解决了这个问题,尽管还有很多其他方法可以做到这一点。
1.我注意到您在两个位置有相同的音符数据:一次在数组中,一次在“note”状态。这只会给予你以后头疼,所以我去掉了note状态。你不需要它。如果你以后想允许一个selectedNote(例如,这样您就可以添加一个编辑功能)、使用另一个状态变量保存你想保存的笔记的id。2然后使用“useMemo”将其选中。请让我知道,如果它会有助于看到完整的。
1.无论noteList.length是否为0或更大,addToList函数都可以执行相同的操作,因此我删除了条件逻辑并更新了逻辑以反映简化的状态设置。
1.不需要“handleTheNoteTxt”函数。要跟踪TextField的值,只需要更新state中的文本值。我们可以使用useState创建一个文本值,并使用该值的set函数。因此,这就是我添加“value”state的地方,并将setValue()调用直接放入TextField的onChange()中。
1.然后,我们可以让“+”按钮调用addNote处理程序,它将能够查看“value”状态以发布新的注解并更新状态变量。

uqdfh47h

uqdfh47h2#

Christian发送的链接有助于您了解正在发生的事情。
这是解决问题的一种方法:

function addToList(e) {
    e.preventDefault();
    if (noteList.length === 0) {
      const newNote = { noteId: 0, txt: note.txt, noteState: false };
      setNote(newNote)
      setNoteList([...noteList, newNote])
    } else {
      const newNote = { noteId: noteList[noteList.length - 1].noteId + 1, txt: note.txt, noteState: false };
      setNote(newNote)
      setNoteList([...noteList, newNote])
    }
  }

相关问题