【问题标题】:React JS & Axios Render after getting response data获取响应数据后 React JS & Axios Render
【发布时间】:2018-01-04 16:43:48
【问题描述】:

我怎样才能让我的组件在从axios GET 请求中获取数据后呈现?
我有以下组件:

class CardPool extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            cardListBacklog: [],
        };
    }

    componentWillMount(){
        axios.get('/cards').then(function(response){
            this.setState({cardListBacklog: response.data});
        }.bind(this));
    }

    render(){

        return(
            <div class="row">
                <Section name="Construction of Component 1 with a huge ass name that wont really fit in the section">
                    <Column columnName="BACKLOG">
                        <CardList id="card-list-1" column="0" cardList={this.state.cardListBacklog}/>
                    </Column>
                </Section>
            </div>
        );
    }
}

class CardList extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            cardList: [],
            laneID: this.props.column
        }
    }

    componentWillMount(){
        this.setState({
            cardList: this.props.cardList,
        });
    }
render(){
        const {connectDropTarget} = this.props;

        return connectDropTarget(
            <div class={"card-list " + this.addClass()} id={this.props.id}>
                {   
                    this.state.cardList ?
                        this.state.cardList.map((card) => {
                            return <Card key={card.id} state={card} laneID={this.state.laneID}/>
                        })
                        : null
                }
            </div>
        );
}

问题在于statecardListBacklog 传递给CardList 没有被更新,CardList 组件中的cardList 仍然为空。我究竟做错了什么?可能是因为我使用props 设置state 属性?

【问题讨论】:

    标签: reactjs axios


    【解决方案1】:

    当响应通过axios 调用到达时,您没有给CardPool 组件重新渲染的机会。

    修改CardPool组件的render函数如下:

    return this.state.cardListBacklog.length
            ? <div class="row">
                <Section name="Construction of Component 1 with a huge ass name that wont really fit in the section">
                    <Column columnName="BACKLOG">
                        <CardList id="card-list-1" column="0" cardList={this.state.cardListBacklog}/>
                    </Column>
                </Section>
              </div>
            : null;
    

    This demo 演示准系统实现

    【讨论】:

    • 这个答案没问题,还有一个问题。 CardList 在其state 中有一个基于props 的列表,我使用react-plugin'(update` 功能对state 进行了修改)。如何使CardPool 中的state 更改时,CardList 中的state 更改?到目前为止,最后一个state 仅在挂载时更改。我可以修改props吗?我只将它们视为只读对象。
    • 您可以在其componentWillReceiveProps 生命周期方法中对CardList 进行state 更改。
    【解决方案2】:

    componentWillMount 生命周期函数只执行一次,因此,当 cardList 在 axios 请求之后在父组件中可用时,子组件的 componentWillMount 已经执行,因此其状态不会更新。设置直接从道具派生的状态也不是一个好主意,您应该从父级传递一个从子级调用的处理程序

    class CardPool extends React.Component{
        constructor(props){
            super(props);
    
            this.state = {
                cardListBacklog: [],
            };
        }
    
        componentWillMount(){
            axios.get('/cards').then(function(response){
                this.setState({cardListBacklog: response.data});
            }.bind(this));
        }
    
        removeCard = (card) => {
            //do what you need to update cardListBacklog
         }
    
        render(){
    
            return(
                <div class="row">
                    <Section name="Construction of Component 1 with a huge ass name that wont really fit in the section">
                        <Column columnName="BACKLOG">
                            <CardList id="card-list-1" column="0" cardList={this.state.cardListBacklog} removeCard={this.removeCard}/>
                        </Column>
                    </Section>
                </div>
            );
        }
    }
    

    class CardList extends React.Component{
        constructor(props){
            super(props);
    
            this.state = {
                cardList: [],
                laneID: this.props.column
            }
        }
    
        render(){
            const {connectDropTarget} = this.props;
    
            return connectDropTarget(
                <div class={"card-list " + this.addClass()} id={this.props.id}>
                    {   
                            this.props.cardList.map((card) => {
                                return <Card key={card.id} state={card} removeCard={() => this.props.removeCard(card)} laneID={this.state.laneID}/>
                            })
                            : null
                    }
                </div>
            );
    }
    

    【讨论】:

      【解决方案3】:

      在 axios 请求后,我能够以这种方式将数据从父级传递给子级:

      父组件

      export default class App extends React.Component {
      constructor(props) {
          super(props);
      
          this.state = {
              peoples: []
          };
      }
      
      componentDidMount() {
          axios.get(`https://swapi.co/api/people`).then(res => {
              const peoples = res.data.results;
              this.setState({ peoples });
          });
      }
      render() {
          const { peoples } = this.state;
          return (
              <div>
                  <Header />
                  <Main peoples={peoples} />
                  <Footer />
              </div>
          );
      }
      

      子组件

      export default class Main extends React.Component {
      constructor(props) {
          super(props);
          this.state = {
              peoples: []
          };
      }
      componentDidUpdate(prevProps) {
          const { peoples } = this.props;
      
          if (peoples !== prevProps.peoples) {
              this.setState({ peoples });
          }
      }
      
      render() {
          const { peoples } = this.state;
          return (
              <div>
                  {peoples
                      ? peoples.map(people => {
                            return <div>people.name</div>;
                        })
                      : null}
              </div>
          );
      }
      

      问题是 axios 请求是异步的,可能只有在子组件挂载后才能接收数据。所以我们需要通过 react hook componentDidUpdate 检查是否收到响应,并将第一个值与收到的新值进行比较,以让 render 正确打印。

      https://reactjs.org/docs/react-component.html#componentdidupdate

      【讨论】:

      • 欢迎来到 SO!当您发布答案时,请尝试解释您的 P.O.V.,因为有更多答案,而不仅仅是粘贴代码,即使是正确的。
      猜你喜欢
      • 2021-07-27
      • 2018-09-19
      • 2020-08-21
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 2021-01-31
      • 2023-01-12
      • 2020-03-22
      相关资源
      最近更新 更多