У меня проблема с craaaaazy.Вот структура приложения.RestaurantContainer
отображает RestaurantInput
, у которого есть форма, чтобы захватить название ресторана.Рестораны отображаются с Restaurant
компонентами в Restaurants
компоненте списка.Код для этих 3 компонентов находится внизу этого поста.
Моя проблема в том, что когда в магазине есть какие-либо рестораны, я получаю эту ошибку:
(Примечание: эта ошибка возникает, еслиЯ добавляю ресторан, используя форму через действие отправки, ИЛИ если я присваиваю RestaurantContainer
начальное состояние, содержащее ресторан - см. Закомментированную строку в mapStateToProps
)
TypeError: Cannot read property 'map' of undefined
Restaurants.render
src/components/restaurants/Restaurants.js:12
9 | return (
10 | <ul>
11 | Your Restaurants:
> 12 | {this.props.restaurants.map(restaurant => {
13 | return <Restaurant key={restaurant.id} restaurant={restaurant} />;
14 | // <li key={restaurant.id}>{restaurant.name}</li>
15 | })}
Если я поменяюсь местамиПри вызове компонента <Restaurant>
для прокомментированного li
он работает нормально.
Итак, я пытаюсь выяснить, почему это происходит, и вот где это сходит с ума.Вы увидите инструкции logger в функции рендеринга Restaurants
и в других местах.Вот что происходит в консоли при загрузке приложения, когда ресторан уже находится в состоянии:
mapStateToProps
RestaurantsContainer props: {restaurants: Array(1), addRestaurant: ƒ, deleteRestaurant: ƒ}
Restaurants this Restaurants {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
Restaurants props {restaurants: Array(1)}
Restaurants this Restaurants {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
Restaurants props {restaurant: {…}}
Restaurants this Restaurants {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
Restaurants props {restaurant: {…}}
Вы увидите, что RestaurantsContainer
отображается один раз, как и ожидалось, но Restaurants
Компонент визуализируется три раза, очень странным образом.
В первый раз его this
и props
- это то, чего вы ожидаете от Restaurants
.({restaurants: Array(1)}
)
Однако второй и третий раз this
- это то, что должно быть для Restaurants
, тогда как props
- это то, что вы ожидаете в Restaurant
(единственное число). ({restaurant: {…}}
)
Наконец, я отмечу, что ни при каких обстоятельствах перечисленная точка останова внутри Restaurant
никогда не попадет.Также я попытался закомментировать все возвращаемое значение Restaurant
render
, без улучшений.
Вот код для компонентов:
// RestaurantsContainer
import React, { Component } from "react";
import RestaurantInput from "../components/restaurants/RestaurantInput";
import Restaurants from "../components/restaurants/Restaurants";
import { connect } from "react-redux";
class RestaurantsContainer extends Component {
render() {
console.log("RestaurantContainer props:", this.props);
return (
<div>
<RestaurantInput
handleSubmit={this.handleSubmit}
addRestaurant={this.props.addRestaurant}
/>
<Restaurants restaurants={this.props.restaurants} />
</div>
);
}
}
const mapStateToProps = state => {
console.log("mapStateToProps");
return {
restaurants: state.restaurants
// restaurants: [{id: 1, name: "burger king"}]
};
};
const mapDispatchToProps = dispatch => {
return {
addRestaurant: name => dispatch({ type: "ADD_RESTAURANT", name: name }),
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(RestaurantsContainer);
// Restaurants
import React, { Component } from "react";
import Restaurant from "./Restaurants";
class Restaurants extends Component {
render() {
console.log("Restaurants this", this);
console.log("Restaurants props", this.props);
return (
<ul>
Your Restaurants:
{this.props.restaurants.map(restaurant => {
return <Restaurant key={restaurant.id} restaurant={restaurant} />;
// <li key={restaurant.id}>{restaurant.name}</li>
})}
</ul>
);
}
}
export default Restaurants;
// Restaurant
import React, { Component } from 'react';
import ReviewsContainer from '../../containers/ReviewsContainer'
class Restaurant extends Component {
render() {
return (
<div>
<li>{this.props.restaurant.name}</li>
</div>
);
}
};
export default Restaurant;