我的组件从服务器获取对象数组并将其设置在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>
答案 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中查看更多内容。