【问题标题】:React - Axios/Fetch/Ajax request after new props passed to child componentReact - 新道具传递给子组件后的 Axios/Fetch/Ajax 请求
【发布时间】:2019-02-13 12:37:50
【问题描述】:

我有两个组件,App 和 Child。我的目标是 App 将 id 传递给 Child,当 Child 将其作为道具接收时,我希望 Child 执行 Axios/Fetch 请求,然后使用结果数据更新自身。我将接受任何为我提供示例 App/Child 源代码的答案,以完成我的示例或提供我的见解,如果这实际上可能是我正在尝试实现的。

我是 React 新手。

// App.js

import React, { Component } from 'react';
import Child from './Child.js';
import './App.css';

class App extends Component {

  state = {
    id: 0
  };

  handleClick() {
    this.setState({
      id: this.state.id + 1
    });
  }

  render() {
    return (
      <div>
        <Child id={this.state.id} />
        <div>
          <button onClick={this.handleClick.bind(this)}>Pass new id down to Child component</button>
        </div>
      </div>
    );
  }
}

export default App;

// Child.js

import React, { Component } from 'react';
import axios from 'axios';

class Child extends Component {
    state = {
        data: null,
        id: 0
    };

    loadData(q, cb) {
        axios.get('http://localhost:3000/foo?q='+this.state.id)
        .then(result => {            
            // ?
            // this.setState would retrigger update and create an infinite updating loop
        })
        .catch(error => {
            console.log('error: ' + error);
        });
    }

    shouldComponentUpdate(nextProps, prevState) {
        console.log('shouldComponentUpdate: nextProps = ' + JSON.stringify(nextProps) + ', prevState = ' + JSON.stringify(prevState));        

        // ??
    }

    getSnapshotBeforeUpdate(nextProps, prevState) {
        console.log('getSnapshotBeforeUpdate: nextProps = ' + JSON.stringify(nextProps) + ', prevState = ' + JSON.stringify(prevState));

        // ?? 
    }

    static getDerivedStateFromProps(nextProps, prevState) {
        console.log('getDerivedStateFromProps: nextProps = ' + JSON.stringify(nextProps) + ', prevState = ' + JSON.stringify(prevState));
        return {
            id: nextProps.id
        };

        // ?? 
    }

    componentDidUpdate() {
        console.log('componentDidUpdate');
    }

  render() {
    return (
      <div>
          <div>data = {this.state.data}</div>
      </div>
    );
  }
}

export default Child;

【问题讨论】:

  • componentDidUpdate() 中,比较prevProps.idthis.state.id。如果它们不同,请致电loadData()。 (我也看不出你的电流怎么会造成无限循环?)
  • 因为 loadData 触发 setState 最终会触发 componentDidUpdate
  • 但这还没有循环。为了让它成为一个循环,componentDidUpdate() 必须总是调用loadData()。但这不会发生,只有当 id 发生变化时。已经 7 周了,你还在坚持这个,甚至没有尝试我的建议吗?

标签: javascript reactjs components


【解决方案1】:

您应该使用当前 id 调用 check prev Id 以避免递归更新。如果你的 props 发生了变化,你只需要确保你只从 props 派生状态,

static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.id !== prevState.id) {
    return {
        id: nextProps.id
    };
 }
 return null;

}

如果您的问题仍然存在,请告诉我

【讨论】:

  • 如果 props 改变并且 state 得到更新,你将在 componentDidUpdate 中调用 loadData
  • 为什么在那儿?它会调用 setState 来更新 componentDidUpdate 一次(一次又一次)
  • 不,你检查了 componentDidUpdate 以避免不必要的 setState 调用
【解决方案2】:

这可能是解决您的问题的一种方法,

首先,您必须更新 getDerivedStateFromProps 中的所有状态数据

static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.id !== prevState.id) {
    // Returning this object is equivalent to setting state using this.setState    
        return {
            id: nextProps.id
            data: loadData(nextProps.id) // Something like this
        };
    }
    return null; // Indicates no state change
}

loadData 方法中的 api 调用可以使用 aync / await 来返回 api 调用中的数据

async loadData(id) {
    try {
        // Make your api call here
        let response = await axios.get('http://localhost:3000/foo?q='+id);
        return await response.json();
    } catch(err) {
        // catches errors both in axios.get and response.json
        // Make sure to not update state in case of any error
        alert(err);
        return null;
    }
}

注意:

  • 这不是完整的解决方案,因为在 loadData 中的 api 调用捕获任何错误的情况下,您可能不想更新状态。
  • 此外,由于您正在使用 api 调用,您可能希望限制将 props 传递给子级的时间,因为它们都会触发不同的 api 调用,您将遇到不可预知的状态。尝试去抖动。

【讨论】:

    猜你喜欢
    • 2019-01-12
    • 2020-12-19
    • 1970-01-01
    • 2018-07-07
    • 2015-04-20
    • 2018-08-01
    • 2021-06-26
    • 2020-10-17
    • 2016-08-17
    相关资源
    最近更新 更多