[英]Child Stateless Functional Component doesn't update even after parent State updates
My parent component has a property in its state called formIsValid
, initially set to false. 我的父组件的状态为
formIsValid
,最初设置为false。 My form also has a submit button. 我的表单也有一个提交按钮。 I want the submit button to be disabled until after some input fields (a first name and a last name input) have data in them.
我希望禁用提交按钮,直到某些输入字段(输入的名字和姓氏)中包含数据之后。
This is what my state looks like: 这是我的状态:
state = {
employees: [],
costEstimates: emptyCosts(),
relationshipOptions: [],
newEmployee: emptyEmployee(),
formIsValid: false
};
This function handles changes to the First and Last name inputs: 此函数处理对名字和姓氏输入的更改:
// handle input into "First Name" and "Last Name" inputs
handleChangeValue = async e => {
const newEmployee = { ...this.state.newEmployee };
newEmployee[e.currentTarget.name] = e.currentTarget.value;
this.setState({ newEmployee });
this.validateIfCanBeSubmitted();
await this.updateCostsData(newEmployee); // this is an api thing, not relevent
};
This is what sets the formIsValid
property in the state. 这就是将
formIsValid
属性设置为状态的原因。 This property is sent as a prop to the Submit button. 此属性作为道具发送到“提交”按钮。
validateIfCanBeSubmitted = () => {
const { firstName, lastName } = this.state.newEmployee;
let formIsValid = firstName && lastName ? true : false;
this.setState({ formIsValid });
};
The Submit button for this is correctly getting disabled if the employee property in the state has its first and last names as empty. 如果状态中的employee属性的名字和姓氏为空,则此“提交”按钮将被正确禁用。 The problem is that it's "off by 1 update."
问题在于它“在1次更新后关闭”。 It's as if the props aren't getting propagated down to the child button component until after the NEXT time the state changes.
好像道具直到下一次状态改变后才传播到子按钮组件。 Here's a gif of the issue:
这是问题的gif:
This is what the child component looks like. 这是子组件的外观。 It's just a regular HTML button, however it's within a Stateless Functional Component, so the issue is not with the component's state:
它只是一个常规的HTML按钮,但是在无状态功能组件中,因此问题不在于组件的状态:
<button
type="button"
onClick={onSubmit}
className={'btn btn-primary mr-1 ' + (formIsValid ? '' : 'disabled')}
disabled={!formIsValid}
>
setState()
is asynchronous! setState()
是异步的!
this.validateIfCanBeSubmitted();
is executed on the old state; 在旧状态下执行; this update
this.setState({ newEmployee });
此更新
this.setState({ newEmployee });
has not been propagated to this.state
when your function is executed. 执行函数时尚未传播到
this.state
。
Make validateIfCanBeSubmitted
an update-function. 使
validateIfCanBeSubmitted
更新功能。
validateIfCanBeSubmitted = ({ newEmployee: { firstName, lastName }}) => {
return {
formIsValid: firstName && lastName ? true : false
};
}
and use it accordingly: 并相应地使用它:
handleChangeValue = async e => {
const {name, value} = e.currentTarget;
const newEmployee = {
...this.state.newEmployee,
[name]: value
};
this.setState({ newEmployee });
this.setState(this.validateIfCanBeSubmitted);
// this is an api thing, not relevant
await this.updateCostsData(newEmployee);
};
Actually, the code in handleChangeValue
should also be in such a function, as it uses the previous state to compute the new one. 实际上,
handleChangeValue
的代码也应该在这样的函数中,因为它使用先前的状态来计算新的状态。
so how about combining them: 那么如何组合它们:
handleChangeValue = e => {
const {name, value} = e.currentTarget;
this.setState((state) => {
const newEmployee = {
...this.state.newEmployee,
[name]: value
};
const { firstName, lastName } = newEmployee;
const formIsValid = firstName && lastName ? true : false;
//and since you never use the returned Promise, why make anything async?
this.updateCostsData(newEmployee);
return { newEmployee, formIsValid };
});
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.