反应组件中断?我无法弄清楚为什么

时间:2018-04-23 09:19:34

标签: javascript reactjs

我的组件从服务器获取对象数组并将其设置在this.state对象中。 但是在渲染时刻(this.state由于this.setState()的fetch方法而更新为componentWillMount(){},我无法正常使用内部状态数组。为什么?它输出我在render(){}函数中未定义数组,我也无法获得数组的recipes.length

有一个组件代码:

import React, { Component } from "react";
import { Router, Route, Link, Switch} from 'react-router';
import '../css/Recipes.css';
import EditRecipe from '../js/EditRecipe';
import DeleteRecipe from '../js/DeleteRecipe';
import CreateProposal from '../js/CreateProposal';
import CreateRecipe from "./CreateRecipe";

class Recipes extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            recipes: [] 
        };
        this.renderRec = this.renderRec.bind(this);
        this.getRec = this.getRec.bind(this);
    }
    renderRec(recipe){
        return <div key={recipe.id}>{recipe.name}</div>
    }
    componentWillMount(){
        this.getRec();
    }
    getRec(_){
        fetch('http://localhost:5000/recipes')
        .then(response => response.json())
        .then(data => {
            this.setState({recipes: data});
        })
        .catch(err => console.log(err))
    }
    render() {
        const recipes = this.state.recipes;
        const howManyRecipes = recipes.length;
        console.log(recipes.data.length);
        const view = howManyRecipes > 0 ? <Route component={this.state.recipes.map(this.renderRec)} /> : <Route component={CreateProposal}/>;
        console.log(view);
        return (
            <div>
                <div>Our community did {howManyRecipes} recipes</div>
                {view}
            </div>     
        );
    }
}

export default Recipes;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

3 个答案:

答案 0 :(得分:1)

问题来自

console.log(recipes.data.length);
在componentWillMount渲染之前

 recipes = this.state.recipes = []

因此recipes.data未定义且无法获取长度值。

删除该行或将该行更改为(例如):

console.log(recipes.data ? recipes.data.length : recipes.data);

答案 1 :(得分:1)

首先,您应该避免在componentWillMount中将api调用移至componentDidMount

第二,

recipes.data并不总是定义的。一旦你成功完成api调用,它将始终被定义。

答案 2 :(得分:1)

避免使用componentWillMount生命周期钩子进行异步操作。请改用componenDidMount

您的请求可能花费太长时间的实际问题因此无法在初始渲染时设置,因此您的数组将保持为初始状态为空。

  

在安装发生之前立即调用componentWillMount()。它在render()之前调用,因此在此方法中设置状态不会触发重新呈现。避免在此方法中引入任何副作用或订阅。

docs中查看更多内容。