【发布时间】:2016-11-09 18:12:01
【问题描述】:
是的,这是一个地狱般的名字。但在我的状态下,我就是想不出一个更好的标题。
问题如下。
在 React 中,在 componentWillMount 期间,我将状态初始化为 null,然后在通过 ajax 从服务器拉取数据后更新该状态。
结构如下:
componentWillMount() {
this.state = { calculator: {} };
initCalculator()
.then(calculator => {
this.setState({ calculator });
})
.catch(err => {
console.log(err);
});
}
数据本身被拉到这里:
function initCalculator() {
const promise = new Promise((resolve, reject) => {
const instance = parseInstance();
const compId = Wix.Utils.getOrigCompId();
axios.get(`/api/calculator?instance=${instance}&compId=${compId}`)
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err);
});
});
return promise;
}
res.data 是带有来自服务器的数据的响应对象。
然后,如您在上面看到的,此数据将传递给 state。
这个状态数据然后被传递给另一个元素:
<Settings tab="Settings" calculator={ this.state.calculator } onUpdate={ this.settingsUpdate.bind(this) }/>
但是,数据并没有在“设置”选项卡的另一端“解析”。
每当我尝试访问计算器对象深处的属性时,它总是向我抛出一个错误。
cannot read property settings of null
这里可以看到
const name = this.props.calculator.settings ? this.props.calculator.settings.name : '';
所以,如果我尝试访问 calculator.settings.name,它会向我抛出类似的错误。
此外,const name 始终设置为 '',即使在第二次重新渲染期间,当推测数据应该已经可用时,因为状态已更新,从而提示在子节点中重新渲染元素。
我明白为什么会这样。至少有点。该对象在它被解析之前被传递,因此在第二次状态更改期间,即this.setState({ calculator });,在状态完全更新之前调用重新渲染。至少我是这么认为的。
如果我console.log(this.props.calculator),我可以正常查看所有数据。但是因为console.log,在点击箭头展开详细信息的同时,它会解析数据。
如果我选择JSON.stringify(this.props.calculator),则数据将全部显示并可用。现在我知道我可以使用JSON.stringify 和JSON.parse 来解决这个问题。但这只是解决我自己可能创造的此类问题的愚蠢方法。
我了解对象通过引用起作用。所以我认为问题出在初始 ajax get 请求或 setState 方法中。
也许有敏锐眼光的人能够看出这里的问题所在。但在这一点上,我只是把头撞在墙上。
【问题讨论】:
-
经过更多测试,我可以得出结论,确实是
this.setState(...);导致了问题。在重新渲染子组件之前,它没有足够快地更新状态。因此,孩子仍然收到状态的旧副本。还没想出解决办法。 -
好吧,所以解决方案似乎是为了在状态更新时更新和重新渲染元素,在某些情况下,您需要在组件上使用
key属性。我会进一步测试它,明天提交我自己问题的答案。 -
谢谢,是的,我本可以返回原始的
axios.get(...),并且功能相同。
标签: javascript ajax reactjs