【发布时间】:2018-04-25 20:32:53
【问题描述】:
我目前正在使用 React 开发一个新应用程序。这是我第一次在 React 中创建东西。该应用程序将显示我们自己的促销活动。
我的初始状态如下:
{
"promotion": {
"name": "",
"campaign": "",
"url": "https://",
"position": 0,
"periods": [
{
"startDateTimeStamp": 1510558814960,
"endDateTimeStamp": 1510558814960,
"variants": [
{
"title": "",
"text": "",
"image": ""
}
]
}
]
}
}
这是从我的 defaultPromotion 常量创建的。这个常量存储在一个单独的文件中,我称之为 api.js
export const defaultPromotion = {
name: '',
campaign: '',
url: 'https://',
position: 0,
periods: [
{
startDateTimeStamp: Date.now(),
endDateTimeStamp: Date.now(),
variants: [
{
title: '',
text: '',
image: '',
},
]
},
]
}
在我的 createPromotion 组件中,它的创建方式如下
let promotionState = api.promotions.defaultPromotion;
this.state = {
promotion: promotionState
};
我可以添加一个新的时期:
addPromotion() {
let promotion = this.state.promotion;
promotion.periods.push( api.promotions.defaultPromotion.periods[0] );
this.forceUpdate();
}
之后,会按预期添加一个新的句点。非常欢迎使用 setState() 执行此操作的建议!所以,我现在的新状态是:
{
"promotion": {
"name": "",
"campaign": "",
"url": "https://",
"position": 0,
"periods": [
{
"startDateTimeStamp": 1510559984421,
"endDateTimeStamp": 1510559984421,
"variants": [
{
"title": "",
"text": "",
"image": ""
}
]
},
{
"startDateTimeStamp": 1510559984421,
"endDateTimeStamp": 1510559984421,
"variants": [
{
"title": "",
"text": "",
"image": ""
}
]
}
]
}
}
现在,我想为这个促销期添加一个新的变体,这就是我现在被困 2 天的地方。
我正在添加一个新的时期如下:
addVariant( periodKey ) {
const promotion = this.state.promotion;
promotion.periods[periodKey].variants.push(api.promotions.defaultPromotion.periods[0].variants[0]);
this.setState({ promotion: promotion });
}
periodKey 在这里是“1”,所以,我期待会为 period[1] 添加一个新的变体,但是,它被添加到两个周期中。现在状态如下:
{
"promotion": {
"name": "",
"campaign": "",
"url": "https://",
"position": 0,
"periods": [
{
"startDateTimeStamp": 1510559984421,
"endDateTimeStamp": 1510559984421,
"variants": [
{
"title": "",
"text": "",
"image": ""
},
{
"title": "",
"text": "",
"image": ""
}
]
},
{
"startDateTimeStamp": 1510559984421,
"endDateTimeStamp": 1510559984421,
"variants": [
{
"title": "",
"text": "",
"image": ""
},
{
"title": "",
"text": "",
"image": ""
}
]
}
]
}
}
有人能解释一下为什么会发生这种情况以及如何以正确的方式添加新变体吗?
提前非常感谢!
更新 1
根据 bennygenel 和 Patrick Hübl-Neschkudla 的回答,我现在的实现如下:
设置初始状态:
constructor(props) {
super(props);
let promotionState = api.promotions.defaultPromotion;
this.state = { ...promotionState };
}
方法:
addVariant( periodKey ) {
this.setState((prevState) => {
const { periods } = prevState;
periods[periodKey].variants.push(
Object.assign({}, { ...periods[periodKey].variants, api.promotions.defaultPromotion.periods[0].variants[0]})
);
return { periods };
});
}
但这仍然是在所有时期设置新的变体。我也尝试了 Benny 的确切代码,但结果相同。该方法被称为
this.props.addVariant( this.props.periodKey );
即使我称它为:
this.props.addVariant(2);
同样的行为正在发生。
更新 2
我现在已经将所有内容都重写为 redux,这样我就可以轻松地在每个组件中访问我的提升,而不是通过某些组件传递它们。根据@mersocarlin 的回答,我现在有以下reducer 案例:
添加句号
case PROMOTION_ADD_PERIOD:
const { periods } = { ...state };
periods.push(api.promotions.defaultPromotion.periods[0]);
state = {
...state,
periods: periods
};
break;
添加句号变量
case PROMOTION_ADD_PERIOD_VARIANT :
state = {
...state,
periods: [
...state.periods[action.payload.period],
{
variants: [
...state.periods[action.payload.period].variants,
api.promotions.defaultPromotion.periods[0].variants[0]
]
}
]
};
break;
以下情况: 添加新的变体、作品、状态:
{
"name": "",
"campaign": "",
"url": "https://",
"position": 0,
"periods": [
{
"startDateTimeStamp": 1510599968588,
"endDateTimeStamp": 1510599968588,
"variants": [
{
"title": "",
"text": "",
"image": ""
}
]
},
{
"startDateTimeStamp": 1510599968594,
"endDateTimeStamp": 1510599968594,
"variants": [
{
"title": "",
"text": "",
"image": ""
}
]
}
]
}
在那之后,添加一个新的变体,有点工作,嗯,变体被添加了,但我失去了我的第二个时期。状态:
{
"name": "",
"campaign": "",
"url": "https://",
"position": 0,
"periods": [
{
"variants": [
{
"title": "",
"text": "",
"image": ""
},
{
"title": "",
"text": "",
"image": ""
}
]
}
]
}
我认为这是我没有看到的一件小事。有人有“PROMOTION_ADD_PERIOD_VARIANT”案例的解决方案吗?
更新 3 将“PROMOTION_ADD_PERIOD”的情况更改如下:
case PROMOTION_ADD_PERIOD:
state = {
...state,
periods: [
...state.periods,
initialState.periods[0]
]
};
break;
更新 4 终于找到了解决办法。请参阅下面的 PROMOTION_ADD_PERIOD_VARIANT 的最终代码:
state = {
...state,
periods: [
...state.periods.map((item, index) => {
if ( index !== action.payload.period ) {
return item;
}
return {
...item,
variants: [
...item.variants,
initialState.periods[0].variants[0]
]
}
})
]
};
非常感谢大家的帮助!!
【问题讨论】:
-
好吧,您正在使用相同的参考,您的
defaultPromotion也是您的this.state.promotion。尝试考虑您希望使用哪个状态引擎(例如 redux 或 mobx)并查看教程如何做到这一点
标签: arrays reactjs object immutability setstate