道具更改时重置状态

时间:2019-12-06 12:26:20

标签: javascript reactjs

可以说我有以下两个组成部分:

const availableTasks = [1, 2, 3];

const Task = () => {
    const [current, setCurrent] = React.useState(0);
    const getNextTask = () => current + 1 < availableTasks.length ? current + 1 : 0;

    return (
        <div className='task-container'>
            <div className='task-information'>
                Some information.
            </div>
            <TaskVote id={availableTasks[current]} key={current}/>
            <button onClick={() => setCurrent(getNextTask())}> Next Task</button>
        </div>
    );
};
const TaskVote = ({ id }) => {
    const [count, setCount] = React.useState(0);

    React.useEffect(() => {
        setInterval(() => setCount(count => count + 1), 1000); // Async data receiving (e.g. websocket)
    }, []);

    return <div> Counting for: {id}, Counted: {count}</div>;
};

TaskVote从websocket接收其数据,并在需要时更新count状态。 (例如,将其替换为时间间隔)

Task呈现有关该任务的一些信息,它呈现TaskVote和一个“下一个任务” button

当用户跳到下一个任务时,TaskVote会收到新密钥,因此它将重新安装,就可以了。

availableTaks中只有一个元素的情况下,key道具不会更改,因此count状态不会重置,即使我希望一旦按钮将其重置也是如此被点击(即使是相同的任务)。

该如何处理?

谢谢!

1 个答案:

答案 0 :(得分:0)

您的问题是您使用一个简单的数字作为密钥,如果您的下一个任务与之前的任务相同,则该密钥不会更新。

这将导致以下渲染多次: <TaskVote id={1} key={0}/>

反应无法确定某些更改。

一个简单的解决方案是保留一个可以用作键的单独状态。

const [voteState, setVoteState] = useState(0)
...
<TaskVote id={availableTasks[current]} key={voteState}/>
<button onClick={() => {
  setCurrent(getNextTask())
  setVoteState((s) => s+1) // always increasing
}}> Next Task</button>

但是,设置多个状态值可能导致多个转售。 您可以通过合并多个值(或通过useReducer)对此进行优化:


const [current, setCurrent] = React.useState({ task: 0, voteButtonState: 0 });

... 
<TaskVote id={availableTasks[current]} key={current.voteButtonState}/>
<button onClick={() => {
  setCurrent((old) => {
    return {
      task: getNextTask(),
      voteButtonState: old.voteButtonState + 1 // always increasing
    }
  }) 
}> Next Task</button>