状态未定义的变量React.js

时间:2017-11-05 17:37:34

标签: javascript reactjs

我试图在我的React组件的状态下存储来自API的产品,然后将它们映射到组件的render函数中,但不知怎的this.state.productsundefined

这是我的组件代码(CategoryProducts.js):

class CategoryProducts extends Component{
    constructor(props){
        super(props); 
        this.state = {}
        this.products = new Products(); 
    }

    async componentWillMount(){
        await this.products.getProductsInCategory(this.props.name).then(
            (val) => {
                this.setState({products: val}); 
            }
        )
    }

    render(){
        return(
            <Container className='content-container'> 
                <Row>
                    <Col md={12}>
                        <h4 className="mb-0">{this.props.name}</h4>
                        <hr></hr>
                    </Col>
                </Row>
                <Row>
                    <Col md={2}>
                        Some space for possible filters in the future 
                    </Col>
                    <Col md={10}>
                        {this.state.products.map(function(item, i){
                            console.log(i); 
                        })}
                    </Col>
                </Row>
            </Container>
        );
    }
}

对API的调用是异步的,这是相应的代码:

Products.js:

export class Products extends API {

    getProducts() {
        return this.get('/products')
    }
    getCategories(){
        return this.get('/products/categories'); 
    }
    getProductsInCategory(_category){
        return this.get('/products/withcategory/' + _category); 
    }
}

这个方法在API类中:

async get(_endpoint) {
        let response = await fetch(this.API_url + _endpoint);
        return response.json();
    }

我希望有人可以帮我解决这个问题

4 个答案:

答案 0 :(得分:0)

第一次调用render()时,API调用可能还没有准备好。您需要在render()函数中考虑这一点。

最简单的方法是:

{this.state.products && this.state.products.map(function(item, i){
                        console.log(i); 
                    })}

这只会在this.state.products具有某些价值时进行映射。

您还可以在加载产品时显示一些加载组件,方法是在render()函数中添加类似的东西。

{ !this.state.products && <SomeLoadingComponent /> }

答案 1 :(得分:0)

您正在将componentWillMount转换为承诺,以便RN不会执行此部分:

 async componentWillMount(){
        await this.products.getProductsInCategory(this.props.name).then(
            (val) => {
                this.setState({products: val}); 
            }
        )
    }

试试这个:

constructor(props){
        super(props); 
        this.state = {
            products: [] //Or whatever suits you best
         }
        this.products = new Products(); 
    }

 componentWillMount(){
        this.products.getProductsInCategory(this.props.name).then(
            (val) => {
                this.setState({products: val}); 
            }
        )
    }

答案 2 :(得分:0)

  在安装发生之前立即调用

componentWillMount()。它在 render()之前调用,因此在此方法中同步调用 setState()将不会触发额外的渲染

您应该避免在componentWillMount生命周期方法中进行API调用。

改为使用componentDidMount

async componentDidMount(){
        await this.products.getProductsInCategory(this.props.name).then(
            (val) => {
                this.setState({products: val}); 
            }
        )
    }

答案 3 :(得分:0)

定义变量

class CategoryProducts extends Component{
constructor(props){
    super(props); 
    this.state = {products : '';}
     
}
enter code here