React DOM不会相应地重新渲染到setState

时间:2020-08-04 06:05:54

标签: javascript reactjs

我正在使用以下JSX代码在React应用程序的一部分上创建待办事项:

<form>
    <div>
        <label htmlFor="subject">Subject: </label>
        <input type="text" value={todo.subject} onChange={e => handleInput(e, 'subject')} name="subject" id="subject"></input>
    </div>
    <div>
        <label htmlFor="duedate">Due date: </label>
        <input type="date" value={todo.duedate} onChange={e => handleInput(e, 'duedate')} name="duedate" id="duedate"></input>
    </div>
    <div>
        <label htmlFor="description">Description: </label>
        <textarea value={todo.description} onChange={e => handleInput(e, 'description')} name="description" id="description"></textarea>
    </div>
    <div>
        <label htmlFor="sidenote">Sidenotes: </label>
        <textarea value={todo.sidenote} onChange={e => handleInput(e, 'sidenote')} name="sidenote" id="sidenote"></textarea>
    </div>
    <button type="submit" onClick={e => handleSubmit(e)}>Submit</button>
</form>

todo状态和handleInput的定义如下:

const [todo, setTodo] = useState({
    'subject': '',
    'duedate': '',
    'description': '',
    'sidenote': ''
});

const handleInput = (e, field) => {
    e.persist();
    setTodo(prevTodo => {
        prevTodo[field] = e.target.value;
        return prevTodo;
    });
}

在输入更改后运行console.log(todo),可以确认状态是否正确更新;但是,这些状态更改不会呈现为输入元素的value。相反,将handleInput更改为以下内容可以解决问题:

const handleInput = (e, field) => {
    e.persist();
    setTodo(prevTodo => {
        let newTodo = {...prevTodo};
        newTodo[field] = e.target.value;
        return newTodo;
    });
}

考虑到两个功能均正确更新了todo状态,是什么原因导致后一个功能正常工作,而前一个却无效?

1 个答案:

答案 0 :(得分:1)

通常,在您的情况下,您必须返回一个浅表复制对象,而不仅仅是修改当前参考状态的键,因为React不会比较键的深处,它只是通过Tabs tabs = new Tabs(); tabs.setOrientation(Tabs.Orientation.VERTICAL); 进行比较以检查当前状态和下一个状态不同,然后决定是否重新渲染,也可以重新编写以使其正常工作:

===