【问题标题】:re-render a functional component on prop change在道具更改时重新渲染功能组件
【发布时间】:2021-12-22 05:58:19
【问题描述】:

子组件接受一个道具并进行计算以显示价值。在第一次加载时,它确实可以工作,但是当父级确实传递新值时,没有任何更新。

家长:

 function Parent(){
       const [v, setV] = useState(0);

    const addNewValue = () =>{
        setV(generateValue({type:'mv', gId: 3})); // generateValue is a function that returns an integer on each call
      }

   return (<div>
          <Child value={v}/>
          <Button onClick={addNewValue}>Calculate</Button>
          
       </div>)

  }

Child.js

 function Child({value}){
       const [baseValue, setBaseValue] = useState(value);


    useEffect(()=>{
      const calculate = calculate(baseValue);
      setBaseValue(calculate);
     },[baseValue]);

   return (<div>
          <Text>{baseValue}</Text>
       </div>)

  }

【问题讨论】:

  • @ArvindMaurya 他们不需要强制重新渲染。道具更改会自动触发重新渲染,所以如果他们没有得到这种行为,他们很可能违反了 React 的规则。但是,我相信他们会重新渲染;只是没有达到他们的预期。

标签: reactjs


【解决方案1】:

传递给useState 的参数仅在第一次渲染时使用一次,因此您将永远不会看到由于value 更新而导致的任何更改。但是,Child 组件仍在重新渲染中

您的useEffect 应该只依赖于value,因为这是它实际需要操作的。否则,您将陷入无限循环,因为每次 baseValue 更改您都会再次更新它。

useEffect(()=>{
  const calculate = calculate(value);
  setBaseValue(calculate);
},[value]);

还要注意,在 state 中存储 props 的值通常是一种反模式。

React docs 提供了一个非常有用的清单,说明了应该不处于什么状态。

  1. 它是通过 props 从父级传入的吗?如果是这样,它可能不是状态:
  2. 它会随着时间的推移保持不变吗?如果是这样,它可能不是状态。
  3. 您可以根据组件中的任何其他状态或道具来计算它吗?如果是这样,它就不是状态。

这可能属于#3(不知道你的全部用例,我不能肯定地说)。在这种情况下,您根本不应该在孩子中使用本地状态。如果是这样,您应该在每次渲染时直接调用calculate,或者如果计算密集,则使用记忆化。

【讨论】:

    【解决方案2】:

    将 value props 传递给 useState 只会在安装阶段更改 baseValue。它不会导致 value prop 的未来更新发生变化

    如果您想以某种方式以最佳方式进行计算,您可以记住计算的值,否则,似乎删除状态并使用道具就可以完成这项工作。看看Uncontrolled component

     function Child({value}){
    
       const baseValue = useMemo(() => calculate(baseValue), [value])
       
       return (<div>
              <Text>{baseValue}</Text>
           </div>)
      }
    

    【讨论】:

      【解决方案3】:

      问题是您的效果不会触发,因为 baseValue 在已安装的组件中没有更改。这是第一次。您需要将效果更新为:

      useEffect(()=>{
            const calculate = calculate(value);
            setBaseValue(calculate);
           },[value]);
      

      【讨论】:

        猜你喜欢
        • 2023-02-15
        • 2021-07-13
        • 1970-01-01
        • 2019-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-27
        • 2019-08-22
        相关资源
        最近更新 更多