React componentDidMount() 初始化状态
Posted
技术标签:
【中文标题】React componentDidMount() 初始化状态【英文标题】:React componentDidMount() initializing state 【发布时间】:2019-01-04 18:36:22 【问题描述】:在 React 中处理一个小项目,我正在使用 Axios 从经过测试的 API 中获取信息。问题是当我拉入数据并尝试更新组件状态时,来自 API 的值没有填充到要在组件中呈现的状态。
我一直在尝试获取如下状态的数据:
componentDidMount()
this.state.databases.forEach(d =>
axios.get(`http://localhost:3204/customer/$d/count`).then(value =>
this.setState( counts: this.state.counts.push(value.data) );
);
);
console.log(this.state);
以前的版本是这样写的:
componentDidMount()
let internalCounts = [];
this.state.databases.forEach(d =>
axios.get(`http://localhost:3204/customer/$d/count`).then(value =>
internalCounts.push(value.data);
);
);
this.setState(count: internalCounts);
这两种情况最终都会得到相同的结果。状态永远不会用新的计数数组真正更新。我怀疑这是由于Axios
和 setState
的异步性质造成的。
什么是让这两者停止相互竞争的简单有效的方法?
【问题讨论】:
【参考方案1】:不要在设置状态后立即使用console.log
,因为它是异步的。回调到setState
。
this.setState(..., () => console.log(...))
或使用console.log
在您的渲染方法中检查您的状态
另外,不要这样做forEach
,如果适合您,请尝试使用Promise.all
一次性提出所有请求。
componentDidMount()
const promiseArray = this.state.databases.map( d =>
axios.get(`http://localhost:3204/$d/count`)
)
Promise.all( promiseArray )
.then( ( results ) =>
const data = results.map( result => result.data);
this.setState( prevState => (
counts: [ ...prevState.counts, ...data]
))
)
【讨论】:
【参考方案2】:问题是我试图改变状态。 (我对不可变数据感到很恐惧……所以我必须习惯一些事情。)
我的解决方案代码如下:
componentDidMount()
this.state.databases.forEach(d =>
axios.get(`http://localhost:3204/$d/count`).then(value =>
this.setState(prevState => (
counts: [...prevState.counts, value.data]
));
);
);
【讨论】:
我更喜欢上面的方法,因为它只设置一次状态,因此您可以避免多次重新渲染。 这是有道理的。但是,计数的数据结构发生了变化,我移至一个对象,并在对象键上进行迭代,以确保使用正确的标题显示正确的数据。 @ForrestLyman,介意我们在问题之外谈论这个吗?我有它的工作,但我想重构只更新一次状态。 当然。您可以通过 forrestswork@gmail.com 或 LinkedIn 联系我。【参考方案3】:在第一个版本中,由于服务的异步特性,您是正确的。您正在记录输出,但这是在服务解决之前发生的。
在第二个(上一个)示例中,您要在状态解析之前设置状态。我会推荐以下方法,创建一个 promise 数组,然后在更新状态之前等待它们全部解决:
componentDidMount()
const promises = [];
this.state.databases.forEach(d =>
promises.push(axios.get(`http://localhost:3204/customer/$d/count`));
);
Promise.all(promises).then(results =>
const internalCounts = [];
results.map(result =>
internalCounts.push(result.data);
);
this.setState(count: internalCounts);
)
【讨论】:
顺便说一句,我建议使用 React Chrome 扩展程序 (chrome.google.com/webstore/detail/react-developer-tools),它使您能够实时检查状态和道具,并使调试这样的事情变得更加容易。【参考方案4】:您的代码存在一些问题:
Array.prototype.push(value.data)
返回新长度,而不是新数组。所以this.setState( counts: this.state.counts.push(value.data) );
正在将state.counts
变成一个数字值this.state.counts.length + 1
,这可能是不希望的。
如果要打印出新的状态,console.log(this.state);
应该放入setState()
的回调参数中。
您之前的版本在setState
之前没有等待axios 调用。你的想法是对的。
【讨论】:
以上是关于React componentDidMount() 初始化状态的主要内容,如果未能解决你的问题,请参考以下文章
async/await 不适用于 ComponentDidMount 中的 react.js
text #react #componentDidMount
React componentDidMount“解析错误:缺少分号”