Javascript 在useState钩子中创建新的状态数组与变异以前的状态
阅读有关Javascript 在useState钩子中创建新的状态数组与变异以前的状态,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,阅读有关useStatehook的问题时,我正在思考setState。我总是有意地使用带有回调选项的setState,以访问前一个状态,并将所有元素(例如)放在一个数组中 因此,我制作了一个功能组件表示的快速示例: const [elems, setElems] = useState([]); const addElemsMutate = (count) => { const newArray = [...elems]; for (let i = 0; i < count;
useState
hook的问题时,我正在思考setState
。我总是有意地使用带有回调选项的setState
,以访问前一个状态,并将所有元素(例如)放在一个数组中
因此,我制作了一个功能组件表示的快速示例:
const [elems, setElems] = useState([]);
const addElemsMutate = (count) => {
const newArray = [...elems];
for (let i = 0; i < count; i++) {
newArray.push(i);
}
setElems(newArray);
};
const addElemsUsePreviousState = (count) => {
for (let i = 0; i < count; i++) {
setElems(previousElems => [...previousElems, i]);
}
}
return <>
<button onClick={() => addElemsMutate(10)}>addElemsMutate</button>
<button onClick={() => addElemsUsePreviousState(10)}>addElemsUsePreviousState</button>
{elems.map((e, index) => <span key={index}>{e}</span>)}
</>
const[elems,setElems]=useState([]);
常量加法器状态=(计数)=>{
常量newArray=[…元素];
for(设i=0;i{
for(设i=0;i[…previousElems,i]);
}
}
返回
Addelemstate(10)}>Addelemstate
addelemsuseprovousstate(10)}>addelemsuseprovousstate
{elems.map((e,index)=>{e})
问题
我理解setState
是异步的,将更改排入队列,并且它不应直接变异
这两个操作的结果在UI上看起来相同。所以我的问题是关于addlemstate
函数中的内容:
谢谢 React更改状态的最佳实践是将当前状态复制到一个新变量中,在那里进行更改,然后更改状态(正如您在示例中所做的那样)
这是因为,当您直接更改状态时,而不是深入复制以前的状态时,您会遇到引用问题,这会留下一些难以发现的错误。更改状态的最佳做法是将当前状态复制到新变量中,在那里进行更改,然后更改状态(正如您在示例中所做的那样)
这是因为,当您直接更改状态时,而不是深入复制以前的状态时,您会遇到引用问题,这可能会留下一些难以发现的错误。这里发生了很多可能不是有意的事情:
- 如注释中所述,
实际上并没有改变状态addelemstate()
enqueuesaddelemsuseprovousstate()
状态更改,而不是由count
调度的单个状态addelemstate()
useState()
的回调形式与useCallback()
结合起来,作为一种小型性能优化
const addElemsCallback = useCallback(count => {
setElems(elems => {
const newElems = [...elems];
for (let i = 0; i < count; i++) {
newElems.push(i);
}
return newElems;
});
}, [setElems]);
const addElemsCallback=useCallback(计数=>{
设置元素(元素=>{
常数newElems=[…elems];
for(设i=0;i
由于
setElems
从不更改,因此addElemsCallback
也不会更改,并且它是唯一需要作为依赖项传递的内容。这里发生的很多事情可能不是有意的:
- 如注释中所述,
实际上并没有改变状态addelemstate()
enqueuesaddelemsuseprovousstate()
状态更改,而不是由count
调度的单个状态addelemstate()
useState()
的回调形式与useCallback()
结合起来,作为一种小型性能优化
const addElemsCallback = useCallback(count => {
setElems(elems => {
const newElems = [...elems];
for (let i = 0; i < count; i++) {
newElems.push(i);
}
return newElems;
});
}, [setElems]);
const addElemsCallback=useCallback(计数=>{
设置元素(元素=>{
常数newElems=[…elems];
for(设i=0;i
由于
setElems
从不更改,因此addElemsCallback
也不会更改,并且它是唯一需要作为依赖项传递的内容。ehm,您的addelemstate
不会变异elems
,它会变异数组的副本。有关读取不可变元素的最常见问题,请参阅@Aprill这是我对该函数命名的愚蠢错误。无论如何,感谢您的链接!嗯,您的加法器状态
不会变异元素
,它会变异数组的一个副本。有关读取不可变元素
的最常见问题,请参阅@Aprillion这是我对该函数命名的愚蠢错误。无论如何链接的nks!不清楚您是否支持AddelemsState
或addElemsUsePreviousState
不清楚您是否支持AddelemsState
或addElemsUsePreviousState
useCallback
是一种性能优化,但它既不能确保更改正确发生代码>或避免不必要的DOM操作
:1.DOM单击
事件通过反应DOM
附加到文档
,交换合成事件处理程序不需要DOM操作..2.重新创建的
是反应元素,而不是DOM元素。3.使用回调
不影响当前组件的重新呈现次数,它会影响useffect(…,[callback])
在渲染后执行+如果作为道具传递,它可能会影响记忆的重新渲染children@Aprillion谢谢,我没有足够的时间来深入研究内部结构。我已经更新了答案以解决您的问题。您是否为useCallback()而烦恼
经常使用?我几乎从不使用useCallback
,因为useffect
中需要的函数可以在它里面定义,而且我不会创建很多以函数为基础的记忆组件。刚才我注意到,你的setState
是未定义的(基于问题代码),你的意思是setElems(elems=>{…return newElems;})
?@Aprillion是的,又一个好消息。谢谢你成为我的IDE!:)useCallbac