简体   繁体   English

更新列表中的某些项目时避免重新渲染所有项目

[英]Avoiding all items rerendering when updating some items in list

really need you help here真的需要你帮忙

I'm loosing a lot of time trying to optimize my app, I think there's something I'm not getting about React我浪费了很多时间来优化我的应用程序,我认为我对 React 有一些不了解

Here's a typical case : I got a form with some interconnected inputs (Changing an input can disabled/enabled anothers) Something looking like my code :这是一个典型案例:我得到了一个带有一些互连输入的表单(更改输入可以禁用/启用其他输入)看起来像我的代码的东西:


const Form = (form)=>{  
  const [inputs, setInputs] = useState(form.inputs)
  const updateInputs = (updates)=>{
    /**
     * Changing some inputs
     */
  }

  return inputs.map(input=>
    <InputComponent {...input} key={input.id} onChange={updateInputs}></InputComponent>
  )
}

My problem is when input is changed, all inputs are rerendering.我的问题是当输入更改时,所有输入都在重新渲染。

Memo/PureComponent is useless here because of the updateInputs function Memo/PureComponent 在这里没用,因为 updateInputs 函数

Can't use "useCallback" hook on "updateInputs" because it's caching "inputs" state, which is updated every change不能在“updateInputs”上使用“useCallback”钩子,因为它缓存“inputs”状态,每次更改都会更新

And yes I use React profiler.是的,我使用 React 分析器。

I got the same issue with checkbox list & radio list.我在复选框列表和单选列表中遇到了同样的问题。 Everytime I got a list with a state shared between items, I got this issue.每次我得到一个在项目之间共享状态的列表时,我都会遇到这个问题。

Thanks to @HaveSpacesuit and this article (not the whole article, just the step #4)感谢@HaveSpacesuit 和这篇文章(不是整篇文章,只是第 4 步)

My issue was : i couldn't put useCallback on "updateInputs" because I was making something like :我的问题是:我不能将 useCallback 放在“updateInputs”上,因为我正在做类似的事情:

  const updateInputs = useCallback((updates)=>{
    const localInputs = [...inputs]
    /* update localInputs */
    setInputs(localInputs)
  }, [])

But doing this would memoize "inputs" state without refreshing it.但是这样做会记住“输入”状态而不刷新它。

Setting "inputs" in the useCallback parameters would create a new function reference every update, which makes useCallback useless.在 useCallback 参数中设置“输入”会在每次更新时创建一个新的函数引用,这使得 useCallback 无用。

The solution is :解决办法是:

  const updateInputs = useCallback((updates)=>{
    setInputs((oldInputs)=>{
      const localInputs = [...oldInputs]
      /*update localInputs*/
      return localInputs
    }
  }, [])

Like this, the function will update fresh "inputs", and the function will keep his reference between rerenders thanks to useCallback.像这样,该函数将更新新的“输入”,并且由于 useCallback,该函数将在重新渲染之间保持引用。

I went from ~200ms to ~25ms on every user interaction我在每次用户交互时从 ~200ms 到 ~25ms

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM