我使用 React hooks 和 React memo 来防止我的功能组件重新渲染,但不起作用?
I use React hooks and React memo to prevent my functional component from re-rendering ,but not work?
我使用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)
当我在Select 组件中更改值时,areEqual 似乎不起作用,上传组件中所有图像的地址将重新加载。为什么...?
这样的表现:
我该怎么办?
重新渲染可能是因为内部状态改变(setValue(value)
)。 React.memo
不会阻止由状态更改引起的重新渲染。
React.memo only checks for prop changes. 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.
您正在将 onChange
参数传递给 Uploader
,例如 onChange={(val) => handleChange(val)}
,因此这有效地在每个渲染器上创建了新函数,因此可能 React.memo
会给出误报.同样在 Uploader
中你有 props.onChange(fileList)
并且 fileList
也可能是每次都是不同的 Array 实例的原因。
除了 @Ramesh Reddy 的回答之外,您还在 Select 更改时调用 setValue
,这也可能是原因,因为您正在使用新值作为 Uploader
.
的支柱
如果这不是原因,您可以添加一个 codesandbox 示例来重现问题。
非常感谢大家~我发现我在Uploader中的值的类型是数组,所以当Select改变时,props.onChange
会导致改变值,所以Uploader会重新加载。
我在上传器组件中添加 useEffect 是这样的:useEffect(() => { setValue(formatValue(props.value)) }, [JSON.stringify(props.value)])
,然后图像将不会重新加载...
我使用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)
当我在Select 组件中更改值时,areEqual 似乎不起作用,上传组件中所有图像的地址将重新加载。为什么...?
这样的表现:
我该怎么办?
重新渲染可能是因为内部状态改变(setValue(value)
)。 React.memo
不会阻止由状态更改引起的重新渲染。
React.memo only checks for prop changes. 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.
您正在将 onChange
参数传递给 Uploader
,例如 onChange={(val) => handleChange(val)}
,因此这有效地在每个渲染器上创建了新函数,因此可能 React.memo
会给出误报.同样在 Uploader
中你有 props.onChange(fileList)
并且 fileList
也可能是每次都是不同的 Array 实例的原因。
除了 @Ramesh Reddy 的回答之外,您还在 Select 更改时调用 setValue
,这也可能是原因,因为您正在使用新值作为 Uploader
.
如果这不是原因,您可以添加一个 codesandbox 示例来重现问题。
非常感谢大家~我发现我在Uploader中的值的类型是数组,所以当Select改变时,props.onChange
会导致改变值,所以Uploader会重新加载。
我在上传器组件中添加 useEffect 是这样的:useEffect(() => { setValue(formatValue(props.value)) }, [JSON.stringify(props.value)])
,然后图像将不会重新加载...