Я создаю счетчик напитков, который будет подсчитывать количество выпитых напитков в рамках проекта по изучению Redux.
У меня есть начальное состояние, в котором есть свойство drink, которое содержит коллекцию напитков и их текущее количество:
//State
{
drinks: {
coffee: 0,
water: 0,
}
//...
}Я создал презентационный компонент Counter:
import React from 'react';
import PropTypes from 'prop-types';
import Button from './Button';
const ucFirst = string => string.charAt(0).toUpperCase() + string.slice(1);
const Counter = ({name, count, onIncrement, onDecrement}) => (
<div className = "counter">
<h2>{ucFirst(name)}</h2>
<span>{count}</span>
<Button onClick = {() => {onIncrement(name)}}>+</Button>
<Button onClick = {() => {onDecrement(name)}}>-</Button>
</div>
);
Counter.propTypes = {
name: PropTypes.string.isRequired,
count: PropTypes.number.isRequired,
onIncrement: PropTypes.func.isRequired,
onDecrement: PropTypes.func.isRequired,
}
export default Counter;За ним следует компонент контейнера DrinkCounter:
import { connect } from 'react-redux'
import { incrementDrink, decrementDrink } from '../actions'
import Counter from '../components/Counter'
const mapStateToProps = (state, ownProps) => ({
count: state.drinks[ownProps.drink],
name: ownProps.drink
})
const mapDispatchToProps = dispatch => ({
onIncrement: drink => dispatch(incrementDrink(drink)),
onDecrement: drink => dispatch(decrementDrink(drink))
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter)Это работает, как ожидалось, если я добавлю
<DrinksContainer name = "coffee" />
в мой компонент App.
Вот где начинается проблема. Я хочу создать еще два компонента: один презентационный и один контейнер, которые будут отображать ключи моего объекта drinks и выводить DrinkCounter для каждого. У меня есть следующий код, но я получаю сообщение об ошибке " Неудачный тип опоры: опора name помечена как обязательная в Counter, но ее значение - undefined "
Вот контейнер List:
import React, {Fragment} from 'react'
import PropTypes from 'prop-types'
import DrinkCounter from '../containers/DrinkCounter'
const List = ({drinks}) => {
return (
<Fragment>
{
Object.keys(drinks).map(
(drink, index) => (<DrinkCounter name = {drink} key = {index} />)
)
}
</Fragment>
)
}
List.propTypes = {
drinks: PropTypes.object.isRequired
}
export default Listа вот контейнер DrinksList:
import React from 'react';
import {connect} from 'react-redux';
import List from '../components/List';
const mapStateToProps = state => ({
drinks: state.drinks
})
export default connect(mapStateToProps)(List);Может ли кто-нибудь объяснить, в чем я ошибаюсь?
Я знаю, но в компоненте List, где отображается карта, я добавляю опору name, как этот <DrinkCounter name = {drink} key = {index} />
как выглядит ваш компонент DrinkCounter?
Код компонента DrinkCounter находится в теле вопроса.
Ну не совсем. вы не показываете ничего, кроме его методов mapStateToProps и mapDispatchToProps. где остальное?
Кстати, вы экспортируете connect(Counter) из DrinkCounter. какая-то причина или опечатка?
DrinkCounter по умолчанию экспортирует connect(mapStateToProps, mapDispatchToProps)(Counter). connect возвращает функцию, которая при вызове с компонентом (в данном случае Counter) возвращает новый компонент, который является переданным компонентом с пропсами, заполненными из состояния. Поэтому, когда я звоню <DrinkCounter name = {drink} key = {index} />, он по сути то же, что и <Counter name = {drink} key = {index} count = {state.drinks[drink]} onIncrement = {incrementDispatchFn} onDecrement = {decrementDispatchFn} />.
В процессе ответа я осознал свою ошибку! Я передаю name в качестве опоры для DrinkCounter, хотя он должен быть drink



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


Я выяснил проблему, в компоненте List я неправильно указываю опору для DrinkCounter. Я передаю name, хотя на самом деле это должен быть drink.
похоже, что в вашем
DrinkCounterвы используете компонентCounter, но вы не передаете ему свойствоname.