【问题标题】:react / functional component / props changed / getDerivedStateFromProps反应 / 功能组件 / 道具改变 / getDerivedStateFromProps
【发布时间】:2019-08-13 10:07:08
【问题描述】:

假设我正在做一个简单的 CRUD 应用程序来响应。我的功能组件基本上就是表单。

  • 在 CREATE 案例中,我通过 props 传入一个空对象
  • 在 UPDATE 案例中,我通过 props 传入了一个带有值的对象(我通过 API 调用获取了父组件中的数据)

我看起来像这样:

const MyForm = (props) => {

 const [myValues, setMyValues] = useState(props.myValues);
 const [errors, setErrors] = useState(0);
 (...)
}

在 UPDATE 情况下,我(当然)遇到了一个问题,即当组件安装时 props.myValues 仍然为空,并且在父组件的 api 调用完成时没有再次设置(更新),因此离开了表单值为空。

使用类组件,我会用 getDerivedStateFromProps() 解决这个问题。功能组件中有类似的东西吗?还是我从一开始就做错了?感谢您的建议!

【问题讨论】:

    标签: javascript reactjs components state


    【解决方案1】:

    另一种方法是Fully uncontrolled component with a key 策略。如果你走那条路,你的组件保持不变:

    const MyForm = (props) => {
    
     const [myValues, setMyValues] = useState(props.myValues);
     const [errors, setErrors] = useState(0);
     (...)
    }
    

    但它的用法还有一点:

    <MyForm myValues={myValues} key={myValues} />
    

    像这样使用 key 属性意味着如果 myValues 更改,将创建此组件的新实例,这意味着您提供给内部 myValues 状态的默认值将重置为任何新值。

    如果您使用useEffect,这可以避免双重渲染,但代价是新组件实例。如果您在单个输入级别执行此操作,我认为这不是问题,但您可能不想重建整个表单。

    【讨论】:

      【解决方案2】:

      当你写作时:

      const [myValues, setMyValues] = useState(props.myValues);
      

      那么 myValues 道具仅用于初始化 myValues 状态。 Dan Abramov 在his latest article 中提到了这一点。
      我建议:
      1. 将 myValues 属性重命名为 initialValues
      2.提交后调用api,根据结果改变你的状态。

      它看起来像:

      const MyForm = (props) => {
        const { initialValues, onSubmit } = this.props
        const [myValues, setMyValues] = useState(initialValues);
        ...
        const handleSubmit = () => {
           // Assume that onSubmit is a call to Fetch API
           onSubmit(myValues).then(response => response.json())
                             .then(updatedValues => setMyValues(updatedValues)) 
        }
      } 
      

      【讨论】:

        【解决方案3】:

        是的,你当然可以使用useEffect

        在您的情况下,代码应如下所示:

        const MyForm = (props) => {
        
         const [myValues, setMyValues] = useState(props.myValues);
         const [errors, setErrors] = useState(0);
        
         useEffect(() => {
           setMyValues(props.myValues);
         }, [props.myValues]);
        
        }
        

        【讨论】:

        • 是的,当然,这就是解决方案。非常感谢!
        • 这是否意味着组件被渲染了两次?一次是在新的 props 到达时,第二次是在 myValues 状态改变之后?
        • @RobAllsopp 是的。您可以通过设置计数器来尝试。
        猜你喜欢
        • 2020-10-13
        • 2019-07-26
        • 2021-05-31
        • 2019-01-14
        • 1970-01-01
        • 2020-04-28
        • 2021-04-20
        • 2019-11-01
        • 1970-01-01
        相关资源
        最近更新 更多