ReactJS setState 与 getDerivedStateFromProps 冲突 [英] ReactJS setState conflicts with getDerivedStateFromProps
问题描述
我正在尝试遵循 https://github.com/reactjs/中的设计模式rfcs/issues/26(请参阅 bvaughn 的回复)并创建 ReactJS 可编辑表单,该表单从服务器读取数据,然后在表单字段中显示,允许使用编辑值,然后将这些数据保存回数据库中.
I am trying to follow the design pattern in https://github.com/reactjs/rfcs/issues/26 (see replies by bvaughn) and create ReactJS editable form, that reads data from the server, show then in the form fields, allows the use to edit values and then save those data back in database.
我有一些基本代码:
const mapStateToProps = state => {
return {
invoice: state.invoice,
invoiceReady: state.invoiceReady,
};
};
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.match.params.id !== prevState.id) {
return update(
prevState, {
['id']: {$set: nextProps.match.params.id},
['invoiceReady']: {$set: false}
});
} else {
return update(
prevState, {
['invoice']: {$set: nextProps.invoice},
['invoiceReady']: {$set: nextProps.invoiceReady}
});
}
}
handleChange(event) {
const state = update(
this.state, {
invoice: {
[event.target.id]: {$set: event.target.value}
}
}
);
this.setState(state);
}
componentDidMount() {
this.requestInvoice();
}
componentDidUpdate(prevProps, prevState) {
if (!this.state.invoiceReady) {
this.requestInvoice();
}
}
并且我的 JSX 代码包含可编辑的字段,例如:
and my JSX code contains editable fields like:
<input
type="text"
className="form-control"
id="invoiceDate"
value={this.state.invoice.invoiceDate}
onChange={this.handleChange}
/>
所以 - 根据提到的模式,我通过 requestInvoice
向服务器发起请求,其他一些组件处理这个动作并接收发票并将其保存到 Redux 存储中,这就是为什么这些数据被自动写入 props.invoice
变量,我通过 getDerivedStateFromProps<进一步将
props.invoice
写入 this.state.invoice
/code> 用于进一步本地处理发票数据.在使用表单的过程中,会引发 handleChange
事件,并在 immutability-helper(更新函数)的帮助下将更新的字段写入新状态并调用 setState
.
So - according to the mentioned pattern I am initiating the request to the server by requestInvoice
, some other components handle this action and receives and saves the invoice into the Redux store and that is why those data are automatically written into the props.invoice
variable and I am further writing props.invoice
into this.state.invoice
by getDerivedStateFromProps
for further local processing of the invoice data. During the work with the form the handleChange
events are raised and with the help of immutability-helper (update function) the updated fields are written into new state and setState
is called.
我的问题是,在 setState
调用期间,React 正在调用 getDerivedStateFromProps
,因此 props.invoice
会覆盖来自用户和那个被处理成 handleChange:setState
函数.
My problem is that during the setState
call the React is calling getDerivedStateFromProps
and so the props.invoice
overwrites any changes that are coming from the user and that ar processed into handleChange:setState
function.
那么 - 如何解决这个问题:setState
和 getDerivedStateFromProps
之间的冲突?
So - how to solve this problem: the conflict between setState
and getDerivedStateFromProps
?
几个选项可能是:
- 我的设计可能有缺陷.例如.也许我不应该尝试将
props.invoice
移动到this.state.invoice
(为什么不呢?)?但另一方面,最好将发票保存到 this.state 中,并确保在编辑发票期间将所有更改应用于this.state.invoice
. - 我应该在
setState
期间阻止执行getDerivedStateFromProps
吗?
- my design can be flawed. E.g. maybe I should not try to move
props.invoice
intothis.state.invoice
(why not?)? But from the other side it would be nice to save invoice into this.state and be sure that all the changes are applied to thethis.state.invoice
during the editing of the invoice. - mybe I should prevent execution of
getDerivedStateFromProps
duringsetState
?
也许其他一些设计模式或代码更适合我的 ReactJS 表单?
Maybe some other design pattern or code is more suitable for my ReactJS form?
我使用的是 ReactJ 16.x
I am using ReactJ 16.x
推荐答案
我得到了以下解决方案 - 在 this.state.stateUpdate
变量的帮助下 - 我认为这是答案对我的问题(如果这不是合理且简洁的解决方案,请发表评论,如果可行,我也可以接受其他答案):
I have arrived at the following solution - with the help of this.state.stateUpdate
variable - and I consider this as the answer to my question (please comment if this is not sound and neat solution, I can accept other answer as well if that works):
const mapStateToProps = state => {
return {
invoice: state.invoice,
invoiceReady: state.invoiceReady,
stateUpdate: false
};
};
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.stateUpdate) {
return update(
prevState, {
stateUpdate: {$set: false}
}
)
}
if (nextProps.match.params.id !== prevState.id) {
return update(
prevState, {
['id']: {$set: nextProps.match.params.id},
['invoiceReady']: {$set: false}
});
} else {
return update(
prevState, {
['invoice']: {$set: nextProps.invoice},
['invoiceReady']: {$set: nextProps.invoiceReady}
});
}
}
handleChange(event) {
const state = update(
this.state, {
invoice: {
[event.target.id]: {$set: event.target.value}
},
stateUpdate: {$set: true}
}
);
this.setState(state);
}
componentDidMount() {
this.requestInvoice();
}
componentDidUpdate(prevProps, prevState) {
if (!this.state.invoiceReady) {
this.requestInvoice();
}
}
这篇关于ReactJS setState 与 getDerivedStateFromProps 冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!