Мой компонент получает массив объектов с сервера и устанавливает его в объект this.state.
Но в момент рендеринга (this.state обновлен до this.setState() из-за метода выборки в настоящий момент 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.info(err))
}
render() {
const recipes = this.state.recipes;
const howManyRecipes = recipes.length;
console.info(recipes.data.length);
const view = howManyRecipes > 0 ? <Route component = {this.state.recipes.map(this.renderRec)} /> : <Route component = {CreateProposal}/>;
console.info(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>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема исходит из
console.info(recipes.data.length);
до того, как componentWillMount отобразит, у вас есть:
recipes = this.state.recipes = []
Следовательно, recipes.data не определен и не может получить значение длины.
Либо удалите строку, либо измените ее на (например):
console.info(recipes.data ? recipes.data.length : recipes.data);
Во-первых, вам следует избегать вызова api в componentWillMount, вместо этого переместите его на componentDidMount.
Второй,
recipes.data не всегда определяется. Он всегда будет определен после успешного вызова API.
Избегайте использования ловушки жизненного цикла componentWillMount для асинхронных операций. Вместо этого используйте componenDidMount.
Фактическая проблема заключается в том, что ваш запрос может занять слишком много времени, поэтому он не будет установлен при первоначальном рендеринге, поэтому ваш массив останется пустым, как в исходном состоянии.
componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method.
См. Больше в документы.
console.info (recipes.data.length); должен быть console.info (recipes.length); для регистрации правильной информации