简体   繁体   English

我使用 React hooks 和 React memo 来防止我的功能组件重新渲染,但不起作用?

[英]I use React hooks and React memo to prevent my functional component from re-rendering ,but not work?

I use React.memo to control re-render, but my component still re-rendered.我使用 React.memo 来控制重新渲染,但我的组件仍然重新渲染。 my code like this:我的代码是这样的:

in my Template Component:在我的模板组件中:

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)

in my Uploader Component:在我的上传器组件中:

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)

when I change value in Select Component, the areEqual seems like not work, the address of all images in Upload Component will reload.当我更改 Select 组件中的值时,areEqual 似乎不起作用,上传组件中所有图像的地址将重新加载。 why...?为什么...?

the performance like this:像这样的表现:

在此处输入图像描述

how can I do?我能怎么做?

The rerender might be because of the internal state change( setValue(value) ).重新渲染可能是因为内部 state 更改( setValue(value) )。 React.memo doesn't prevent rerender caused by a state change. React.memo不会阻止由 state 更改引起的重新渲染。

React.memo only checks for prop changes. React.memo 仅检查 prop 更改。 If your function component wrapped in React.memo has a useState or useContext Hook in its implementation, it will still rerender when state or context change.如果包装在 React.memo 中的 function 组件在其实现中具有 useState 或 useContext Hook,则它仍会在 state 或上下文更改时重新呈现。

Docs文档

You're passing the onChange param to Uploader like onChange={(val) => handleChange(val)} so this effectively creates new function on each render and probably React.memo gives false positive because of this.您正在将onChange参数传递给Uploader ,例如onChange={(val) => handleChange(val)}所以这有效地在每个渲染上创建新的 function 并且React.memo可能因此而给出误报。 Also in Uploader you have props.onChange(fileList) and fileList might also be the reason if it's a different Array instance everytime.同样在Uploader中,您有props.onChange(fileList)fileList也可能是原因,如果它每次都是不同的 Array 实例。

In addition to @Ramesh Reddy 's answer, you're calling setValue upon Select changes too, that could also be the reason, since you're using the new value as prop to Uploader .除了@Ramesh Reddy的回答之外,您还在 Select 更改时调用setValue ,这也可能是原因,因为您使用新值作为Uploader的道具。

If this is not the reason, you can add a codesandbox sample with reproduction of the issue.如果这不是原因,您可以添加带有重现问题的代码框示例。

thanks all very much~I find that the type of my value in Uploader is array, so when Select change, props.onChange will be lead to change the value, so Uploader will reload.非常感谢~我发现我在Uploader中的值的类型是数组,所以当Select改变时,会导致props.onChange改变值,所以Uploader会重新加载。

I add useEffect in Uploader Component like this: useEffect(() => { setValue(formatValue(props.value)) }, [JSON.stringify(props.value)]) ,and then the images will not reload...我在 Uploader 组件中添加 useEffect ,如下所示: useEffect(() => { setValue(formatValue(props.value)) }, [JSON.stringify(props.value)]) ,然后图像不会重新加载...

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

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