反应 componentDidMount() 初始化状态
React componentDidMount() initializing state
我正在使用 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
and setState
.
的异步性质造成的
有什么简单有效的方法可以让这两个停止相互竞争?
您的代码存在一些问题:
Array.prototype.push(value.data)
returns 新长度,不是新数组。所以 this.setState({ counts: this.state.counts.push(value.data) });
正在将 state.counts
变成一个数字值 this.state.counts.length + 1
,这可能是不需要的。
- 如果你想打印出新的状态,
console.log(this.state);
应该放在setState()
的回调参数中。
- 您之前的版本在
setState
之前没有等待 axios 调用。你的想法是正确的。
在第一个版本中,您是正确的,这是由于服务的异步性质。您正在记录输出,但这是在服务解决之前发生的。
在第二个(上一个)示例中,您在解析之前设置状态。我会推荐以下方法,创建一个承诺数组,然后在更新状态之前等待所有承诺解决:
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});
})
}
不要在设置状态后立即使用 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]
}))
})
}
问题是我试图改变状态。 (我一直对不可变数据感到恐惧......所以我必须习惯一些东西。)
我的解决代码如下:
componentDidMount(){
this.state.databases.forEach(d => {
axios.get(`http://localhost:3204/${d}/count`).then(value => {
this.setState(prevState => ({
counts: [...prevState.counts, value.data]
}));
});
});
}
我正在使用 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
and setState
.
有什么简单有效的方法可以让这两个停止相互竞争?
您的代码存在一些问题:
Array.prototype.push(value.data)
returns 新长度,不是新数组。所以this.setState({ counts: this.state.counts.push(value.data) });
正在将state.counts
变成一个数字值this.state.counts.length + 1
,这可能是不需要的。- 如果你想打印出新的状态,
console.log(this.state);
应该放在setState()
的回调参数中。 - 您之前的版本在
setState
之前没有等待 axios 调用。你的想法是正确的。
在第一个版本中,您是正确的,这是由于服务的异步性质。您正在记录输出,但这是在服务解决之前发生的。
在第二个(上一个)示例中,您在解析之前设置状态。我会推荐以下方法,创建一个承诺数组,然后在更新状态之前等待所有承诺解决:
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});
})
}
不要在设置状态后立即使用 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]
}))
})
}
问题是我试图改变状态。 (我一直对不可变数据感到恐惧......所以我必须习惯一些东西。)
我的解决代码如下:
componentDidMount(){
this.state.databases.forEach(d => {
axios.get(`http://localhost:3204/${d}/count`).then(value => {
this.setState(prevState => ({
counts: [...prevState.counts, value.data]
}));
});
});
}