反应 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.

的异步性质造成的

有什么简单有效的方法可以让这两个停止相互竞争?

您的代码存在一些问题:

  1. Array.prototype.push(value.data) returns 新长度,不是新数组。所以 this.setState({ counts: this.state.counts.push(value.data) }); 正在将 state.counts 变成一个数字值 this.state.counts.length + 1,这可能是不需要的。
  2. 如果你想打印出新的状态,console.log(this.state);应该放在setState()的回调参数中。
  3. 您之前的版本在 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]
            }));
         });
    });
}