Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应/功能组件/道具更改/从道具获取衍生状态_Javascript_Reactjs_Components_State - Fatal编程技术网

Javascript 反应/功能组件/道具更改/从道具获取衍生状态

Javascript 反应/功能组件/道具更改/从道具获取衍生状态,javascript,reactjs,components,state,Javascript,Reactjs,Components,State,假设我在react中做一个简单的CRUD应用程序。我的功能组件基本上就是形式 在创建案例中,我通过道具传入一个空对象 在更新案例中,我通过props传入一个带有值的对象(我通过API调用获得父组件中的数据) 我看起来像这样: const MyForm = (props) => { const [myValues, setMyValues] = useState(props.myValues); const [errors, setErrors] = useState(0); (

假设我在react中做一个简单的CRUD应用程序。我的功能组件基本上就是形式

  • 在创建案例中,我通过道具传入一个空对象
  • 在更新案例中,我通过props传入一个带有值的对象(我通过API调用获得父组件中的数据)
我看起来像这样:

const MyForm = (props) => {

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

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

 useEffect(() => {
   setMyValues(props.myValues);
 }, [props.myValues]);

}
在UPDATE的例子中,我(当然)遇到了这样一个问题:当安装组件时,props.myValues仍然是空的,并且当父组件的api调用完成时,没有再次设置(更新),因此表单值为空


使用类组件,我将使用getDerivedStateFromProps()解决这个问题。功能组件中是否有类似的内容?还是我从一开始就做错了?谢谢你的建议

是的,您当然可以使用
useffect

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

const MyForm = (props) => {

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

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

 useEffect(() => {
   setMyValues(props.myValues);
 }, [props.myValues]);

}
当你写作时:

const [myValues, setMyValues] = useState(props.myValues);
那么myValues道具只用于初始化myValues状态。 丹·阿布拉莫夫(Dan Abramov)在《华盛顿邮报》中提到了这一点。
我建议:
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)) 
  }
} 

另一种方法是战略。如果您选择该路线,您的组件将保持不变:

const MyForm = (props) => {

 const [myValues, setMyValues] = useState(props.myValues);
 const [errors, setErrors] = useState(0);
 (...)
}
但它的用途还有一个额外的部分:

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

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


这避免了在
useffect
时获得的双重渲染,但要以新组件实例为代价。如果您在个人输入级别执行此操作,我不认为这是一个问题,但您可能不希望重建整个表单。

是的,当然,这是解决方案。谢谢!这是否意味着组件渲染两次?新道具到达时一次,以及
myValues
状态更改后的第二次?@RobAllsopp yes。你可以设置一个柜台来试试。