我试图使用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`

推荐答案

以下是一个经过一些简化和重构的固定版本.

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

[编辑-添加推理信息]

  1. @Christian Fritz的注释涵盖了您的实际错误--当您使用useState进行更新时,新值实际上不会反映在下面的代码行中.我在这里用nextID状态变量解决了这个问题,尽管有很多其他方法可以做到这一点.

  2. 我注意到有两个地方有相同的笔记数据:一次在数组中,另一次处于"笔记"状态.那只会让你以后头疼,所以我摆脱了笔记状态.你不需要它.如果您想在以后允许选定的 sticky (例如,您可以添加编辑功能),请使用另一个状态变量来保存您想要保存的 sticky 的ID.然后使用"useMemo"将其选中.如果能完整地看到这一点,请让我知道是否有帮助.

  3. 您的addToList函数可以执行相同的操作,而不管note List.long是否为0或更大,因此我删除了条件逻辑,并更新了逻辑以反映简化的状态设置.

  4. 不需要您的"handleTheNoteTxt"函数.要跟踪TextField值,只需更新状态中的文本值.我们可以使用useState创建一个文本值,并使用该值的set函数.这就是我添加"Value"状态的地方,并将setValue()调用直接放入TextField的onChange()中.

  5. 然后,我们可以让"+"按钮调用addNote处理程序,它将能够查看"Value"状态以发布新笔记并更新状态变量.

Reactjs相关问答推荐

我想将状态设置为true,直到每一张卡片都生成并在多姆中呈现

无法覆盖MUI工具栏上的左右填充,除非使用!重要

如何防止使用useCallback和memo重新渲染

有没有办法将在服务器端全局获取的一些数据传递到Next&>13应用程序目录中的客户端组件?

是否在Extra Reducer完成作业(job)时触发createListenerMiddleware?

react ';S使用状态不设置新状态

在Reaction中导入';图片&文件夹时出错

自定义变量默认、聚焦和填充时所需TextField中标签的星号 colored颜色

Antd V5组件自定义主题

在react的useEffect钩子中,我的函数被调用,但只有第一个函数能够改变状态,第二个函数无法改变状态.

在MongoDB中,如何获取最后N条记录中字段不为空或不为空字符串的数据

React对象值下降2次而不是1次

React:如何使用条件渲染和react 挂钩来更新另一个组件的状态?

React Native Realm 应用程序在发布构建后崩溃

@react-three/postprocessing 没有匹配的从 three.module.js 导出以导入WebGLMultisampleRenderTarget

如果传递给挂钩的数据需要事先修改,如何使用自定义挂钩?

Wordpress 插件在激活时创建一个 React Public 页面

当状态改变时如何执行一些动作,但只针对第一次更新?

为什么重新渲染不会影响 setTimeout 的计数?

将 C# Razor 条件块转换为 React.js 代码