【问题标题】:I use React hooks and React memo to prevent my functional component from re-rendering ,but not work?我使用 React hooks 和 React memo 来防止我的功能组件重新渲染,但不起作用?
【发布时间】:2020-07-21 08:38:22
【问题描述】:

我使用 React.memo 来控制重新渲染,但我的组件仍然重新渲染。 我的代码是这样的:

在我的模板组件中:

const Template = (props: Props) => {
  const { propsValue, data } = props
  const [value, setValue] = useState(propsValue)

  const handleChange = (value) => {
    setValue(value)
    props.onChange(value)
  }
  
  return (
    <div>
      {info.type === 'input' && <Input value={value} onChange={(event, val) => handleChange(val) onBlur={(event) => handleBlur()} />
      {info.type === 'image' && <Uploader multiple value={value} uploadUrl={data.uploadUrl} onChange={(val) => handleChange(val)} />
      {info.type === 'select' && <Select onChange={(val) => handleChange(val)} />
    </div>
  )
}

const areEqual = (prevProps, nextProps) => {
  if (JSON.stringify(prevProps) !== JSON.stringify(nextProps)) {
    return false
  }
  return true
}

export default React.memo(EditTemplate, areEqual)

在我的上传器组件中:

const Uploader = props => {
  const [value, setValue] = useState(props.value)
  let { uploadUrl, multiple } = props

  const handleChange = ({ file, fileList }) => {
    if (file.status === 'done') {
      setValue(fileList)
      props.onChange(fileList)
    } else {
      setValue(fileList)
    }
  }

  return (
     <div>
       <Upload fileList={value} multiple={multiple} action={uploadUrl} onChange={handleChange} />
     </div>
  )
}

const areEqual = (prevProps, nextProps) => {
  if (JSON.stringify(prevProps) !== JSON.stringify(nextProps)) {
    return false
  }
  return true
}

export default React.memo(Uploader, areEqual)

当我在选择组件中更改值时,areEqual 似乎不起作用,上传组件中所有图像的地址将重新加载。为什么...?

这样的表现:

我该怎么办?

【问题讨论】:

  • React memo:此方法仅作为性能优化存在。不要依赖它来“阻止”渲染,因为这可能会导致错误。直接来自文档。如果info.type 发生变化,则Uploader 被挂载/卸载。不要过早优化。
  • 对于这些情况,您应该考虑在重新渲染之前在组件内部使用useMemo

标签: javascript reactjs react-hooks render react-memo


【解决方案1】:

重新渲染可能是由于内部状态更改(setValue(value))。 React.memo 不会阻止由状态更改引起的重新渲染。

React.memo 仅检查 prop 更改。如果你的函数组件 包裹在 React.memo 里面有一个 useState 或者 useContext Hook 实现,它仍然会在状态或上下文发生变化时重新渲染。

Docs

【讨论】:

  • 但是为什么选择中的状态变化会导致上传者图像重新加载...?看不懂……
  • 因为答案中说明的原因。 UploaderTemplate 组件的子组件。分配给 select 的 onChange 的函数正在更改触发重新渲染的状态。
  • 我尝试在模板组件中注释掉setValue(value),但图像仍会重新加载。
  • props.onChange(value) 怎么样?还有一些其他的事情可能会导致重新渲染。浏览文档。使用useCallbackuseMemo 记住有意义的事情。
【解决方案2】:

您将onChange 参数传递给Uploader,就像onChange={(val) =&gt; handleChange(val)} 这样有效地在每次渲染上创建新函数,并且React.memo 可能因此给出误报。同样在 Uploader 你有 props.onChange(fileList)fileList 如果它每次都是不同的 Array 实例也可能是原因。

除了 @Ramesh Reddy 的回答之外,您还在 Select 更改时调用 setValue,这也可能是原因,因为您使用新值作为支持Uploader.

如果不是这个原因,您可以添加一个代码框示例来重现问题。

【讨论】:

    【解决方案3】:

    非常感谢~我发现我在Uploader中的值的类型是数组,所以当Select change时props.onChange会导致值改变,所以Uploader会重新加载。

    我在 Uploader 组件中添加 useEffect 如下:useEffect(() =&gt; { setValue(formatValue(props.value)) }, [JSON.stringify(props.value)]),然后图像不会重新加载...

    【讨论】:

      猜你喜欢
      • 2023-02-26
      • 2019-05-29
      • 2019-07-28
      • 2021-02-14
      • 1970-01-01
      • 2019-07-23
      • 2019-07-06
      • 2021-09-29
      相关资源
      最近更新 更多