Редукторы Redux, инициализирующие один и тот же ключ состояния

Я возился с 'simpleest-redux-example' на github, и я добавил второй редуктор, который уменьшает состояние. сосчитать. Если у меня есть редукторы с приращением и уменьшением в выражении оператора switch, он работает нормально. Упражнение, которое я хотел выполнить, состояло в том, чтобы разделить редукторы на максимально возможное количество модульных элементов. Этот код вызывает ошибку, указывающую, что count undefined.

import React from 'react';
import { createStore, combineReducers } from 'redux';
import { Provider, connect } from 'react-redux';

// React component
class Counter extends React.Component {
  render(){
    const { value, onIncreaseClick, onDecreaseClick } = this.props;
    return (
      <div>
        <span>{value}</span>
        <button onClick={onIncreaseClick}>Increase</button>
        <button onClick={onDecreaseClick}>Decrease</button>
      </div>
    );
  }
}

// Action:
const increaseAction = {type: 'increase'};
const decreaseAction = {type: 'decrease'};

// Reducer:
function counter(state, action) {
  let count = state.count;
  switch(action.type){
    case 'increase':
      return {count: count+1};
    default:
      return state;
  }
}
function decrementer(state, action) {
  let count = state.count;
  switch(action.type){
    case 'decrease':
      return {count: count -1};
    default:
      return state;
  }
}
const rootReducer = combineReducers({
  counter,
  decrementer
})

// Store:
let store = createStore(rootReducer, {count: 0});

// Map Redux state to component props
function mapStateToProps(state)  {
  console.log("mapStatetoProps heyyyy");
  return {
    value: state.count
  };
}

// Map Redux actions to component props
function mapDispatchToProps(dispatch) {
  console.log("mapDispatchtoProps heyyyy");
  return {
    onIncreaseClick: () => dispatch(increaseAction),
    onDecreaseClick: () => dispatch(decreaseAction)
  };
}

// Connected Component:
let App = connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter);

React.render(
  <Provider store={store}>
    {() => <App />}
  </Provider>,
  document.getElementById('root')
);

Ответы

Ответ 1

Редукторы перешли к combineReducers получить разные части объекта состояния.

Результирующий редуктор вызывает каждый дочерний редуктор и собирает результаты в один объект состояния. Форма объекта состояния соответствует ключам прошедшего reducers.

(Акцент мой)

Итак, объект внутреннего состояния будет выглядеть как

{
  counter: result of passing `state.counter` into counter reducer
  decrementer: result of passing `state.decrementer` into decrementer reducer
}

Это аналогично наличию отдельных хранилищ в приложении потока, где каждый магазин управляет своей собственной "частью" глобального состояния приложения.

Поскольку вы действительно хотите, чтобы эти два редуктора работали на одной и той же части объекта состояния, вы действительно хотите что-то большее, чем reduce-reducers, хотя это очень легко реализовать себя - просто передайте состояние в каждый редуктор, в свою очередь, уменьшив начальное состояние с новым состоянием от каждого редуктора.

На самом деле, это так просто, реализация - всего несколько строк:

export default function reduceReducers(...reducers) {
  return (previous, current) =>
    reducers.reduce(
      (p, r) => r(p, current),
      previous
    );
}

и ваш rootReducer будет

const rootReducer = reduceReducers(counter, decrementer);

Ответ 2

Ты так близко! Уловка заключается в том, что когда вы используете combReducers, он фактически разбивает "состояние" таким образом, что состояния редукторов, которые вы используете, являются свойствами объекта "state".

Таким образом, чтобы подавать их параметры по умолчанию следующим образом: let store = createStore(rootReducer, {counter: {count: 0}, decrementer: {count:0}});