如何在React中的this.setState之后正确渲染组件

时间:2019-12-25 11:23:14

标签: javascript reactjs

我有这个React组件

import React, { Component } from "react";

export default class ResourceForField extends Component {
    constructor() {
        super();
        this.state = {
            resources: [],
        };
    }
    componentDidMount() {
        // get the resources from the Link props and save it into the state
        this.setState({
            resources: this.props.location.resources,
        });
    }

    // This component gets the id of current learningField from the url
    // and the rest(like the resources) from the Link component
    render() {
        return (
            <div>
                {this.state.resources.map(res => (
                    <div>test</div>
                ))}
            </div>
        );
    }
}

它从Link组件获取资源,并且工作正常。如果我从开发工具中检查Component的状态,则状态看起来正确。我以我的逻辑认为这应该可行。因此,首先,状态为空,将渲染组件,因为状态为空,因此不渲染任何组件。然后,调用setState,它获取所有资源并将其保存到状态中,然后该组件将重新呈现,并且它应该可以工作,但不能。我收到一个TypeError: Cannot read property 'map' of undefined错误。正确的方法是什么?如何解决?

3 个答案:

答案 0 :(得分:2)

尝试此代码:

import React, { Component } from "react";

export default class ResourceForField extends Component {
    constructor() {
        super();
        this.state = {
            resources: this.props && this.props.location && this.props.location.resources?this.props.location.resources:[],
        };
    }
    componentDidMount() {

    }

    // This component gets the id of current learningField from the url
    // and the rest(like the resources) from the Link component
    render() {
        return (
            <div>
                {this.state.resources.map(res => (
                    <div>test</div>
                ))}
            </div>
        );
    }
}

或直接使用道具

import React, { Component } from "react";

export default class ResourceForField extends Component {
    constructor() {
        super();

    }

    // This component gets the id of current learningField from the url
    // and the rest(like the resources) from the Link component
    render() {
        return (
            <div>
                { 
                  this.props && this.props.location && 
                  this.props.location.resources
                    ?this.props.location.resources.map(res => (
                    <div>test</div>
               ))
             :null
              }
            </div>
        );
    }
}

或使用componentWillReceivePropsgetDerivedStateFromProps生命周期方法。 检查this.props.location.resources是否为array。 查看更多:https://hackernoon.com/replacing-componentwillreceiveprops-with-getderivedstatefromprops-c3956f7ce607

答案 1 :(得分:0)

对于第一个检查是<table id="mainTable" class=" table table-striped table-bordered text-center"> <thead> <tr> <th></th> <th>Year 1</th> <th>Year 2</th> <th>Year 3</th> <th>Year 4</th> <th>Year 5</th> </tr> </thead> <tbody> <tr> <td>Retail Price</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> </tr> <tr> <td>Retail Quantity</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> </tr> <tr> <td>Affiliate Price</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> </tr> <tr> <td>Affiliate Quantity</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> </tr> <tr> <td>Whole Prize</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> </tr> <tr> <td>Whole Quantity</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> </tr> <tr> <td>Custom Prize</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> </tr> <tr> <td>Custom Quantity</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> <td>10</td> </tr> <tr> <td>Unit Cost</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> <td>1780</td> </tr> </tbody> <tfoot> <tr> <th><strong>TOTAL</strong></th> <th></th> <th></th> <th></th> <th></th> <th></th> </tr> </tfoot> </table> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> $(document).ready(function(){ $('#mainTable').editableTableWidget() }); </script> 数组,或者如果可以更改数据类型可以添加检查,则可以使用lodash this.props.location.resources或与js一起使用:

isArray

或者您也可以像这样使用hooks

import React, { Component } from "react";

    export default class ResourceForField extends Component {
        constructor() {
            super();
            this.state = {
                resources: [],
            };
        }
        componentDidMount() {
            // get the resources from the Link props and save it into the state
            Array.isArray(this.props.location.resources) {
              this.setState({
                  resources: this.props.location.resources,
              });
            }
        }

        // This component gets the id of current learningField from the url
        // and the rest(like the resources) from the Link component
        render() {
            return (
                <div>
                    {this.state.resources.map(res => (
                        <div>test</div>
                    ))}
                </div>
            );
        }
    }

答案 2 :(得分:0)

如果ResourceForField的内部状态没有改变并且始终等于其prop,则不应将prop保存在该状态中。您可以创建一个纯功能组件。

还要注意,没有什么可以阻止您从构造方法中的props初始化状态。也就是说,您无需等待组件安装即可访问道具。

因此,我将为ResourceForField编写以下组件:

function ResourceForField({resources = []}) {
    return (
        <div>
        {
            resources.map(res => (<div>test</div>))
        }
        </div>
    );
}