React JS 和 Axios Render 获取响应数据后

React JS & Axios Render after getting response data

如何才能让我的组件在从 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>
        );
}

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

设置 state 属性

componentWillMount 生命周期函数只执行一次,因此,当 cardList 在 axios 请求后在父级可用时,子组件的 componentWillMount 已经执行,因此它的状态未更新。设置直接从 props 派生的状态也不是一个好主意,你应该传递一个从 Child

调用的父级的处理程序
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>
        );
}

当响应通过 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 演示准系统实现

在 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 接收到响应,并将第一个值与接收到的新值进行比较,以便正确渲染打印。

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