Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在useState钩子中创建新的状态数组与变异以前的状态_Javascript_Reactjs_React Hooks - Fatal编程技术网

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()
      实际上并没有改变状态
    • addelemsuseprovousstate()
      enqueues
      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()
      实际上并没有改变状态
    • addelemsuseprovousstate()
      enqueues
      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