在属性更改时重新渲染一个功能组件
在属性更改时重新渲染一个功能组件
子组件接受一个属性并进行计算以显示值。在首次加载时,它能正常工作,但当父组件传递新值时,没有更新。
父组件:
function Parent() { const [v, setV] = useState(0); const addNewValue = () => { setV(generateValue({ type: 'mv', gId: 3 })); // generateValue是一个在每次调用时返回整数的函数 } return ( <>> ) }
Child.js:
function Child({ value }) { const [baseValue, setBaseValue] = useState(value); useEffect(() => { const calculate = calculate(baseValue); setBaseValue(calculate); }, [baseValue]); return ({baseValue} ) }
当将值作为prop传递给useState时,只会在挂载阶段改变baseValue,而不会在将来的更新中改变值prop。如果要以某种方式进行优化计算,可以将计算出的值记忆起来,否则,似乎移除状态并使用props就可以完成工作。查看无控制组件。
解决方法是使用useMemo将计算结果缓存起来,然后将value作为依赖项传递给useMemo,以便在value发生变化时重新计算baseValue。
下面是修改后的代码示例:
function Child({ value }) { const baseValue = useMemo(() => calculate(baseValue), [value]); return (); }{baseValue}
这样,当value发生变化时,Child组件将重新渲染,并且baseValue将使用最新的value进行计算。
当我们在一个已经挂载的组件中使用useEffect钩子函数时,如果我们希望在prop发生变化时重新渲染函数组件,可能会遇到一个问题。问题在于,当组件挂载时,useEffect函数不会触发,因为在挂载时,prop的值并没有发生改变。然而,当prop的值发生变化时,我们希望重新渲染组件。
要解决这个问题,我们可以更新我们的useEffect函数。我们可以将需要触发重新渲染的prop作为useEffect的第二个参数传入。这样,当prop的值发生变化时,useEffect函数就会重新触发,从而重新渲染组件。
具体实现如下:
useEffect(() => { const calculate = calculate(value); setBaseValue(calculate); }, [value]);
在这个例子中,我们使用了一个函数calculate来计算baseValue的值。当prop value发生变化时,我们重新计算baseValue,并通过setBaseValue函数更新state。这样,组件就会重新渲染,并展示新的baseValue。
通过这种方式,我们可以实现在prop发生变化时重新渲染函数组件的效果。这对于需要根据不同的prop值来展示不同内容的组件非常有用。
问题的原因是在使用useState
时,传递的参数只会在第一次渲染时使用一次,所以当value
更新时,你永远看不到任何变化。然而,Child
组件仍然重新渲染。
解决方法是确保useEffect
只依赖于value
,因为这是它实际上需要操作的内容。否则,你会陷入无限循环,因为每次baseValue
更改时,你都在更新它。
useEffect(() => { const calculate = calculate(value); setBaseValue(calculate); }, [value]);
还要注意,将props中的值存储在状态中通常是一种反模式。React文档提供了一个非常有用的检查清单,列出了不应该包含在状态中的内容。
1. 它是通过props从父组件传递过来的吗?如果是,那么它可能不是状态。
2. 它在时间上保持不变吗?如果是,那么它可能不是状态。
3. 你能根据组件中的其他状态或props计算出它吗?如果可以,那么它不是状态。
根据上述检查清单,这个问题可能属于第三种情况(如果不了解完整的用例,无法确定)。在这种情况下,你不应该在子组件中使用局部状态。如果是这样的话,你应该在每次渲染时直接调用calculate
,或者如果计算量很大,可以使用记忆化。