Redux Dataflow от редуктора к контейнеру - PullRequest
1 голос
/ 03 августа 2020

Поскольку я только что начал работать с redux, вот важный вопрос о потоке данных в redux

Насколько я понимаю, я создал компонент как CountN:

import React from 'react'

import styles from '../../features/counter/Counter.module.css'


const CountN = (props) => {
     
    const {countValue,actions} = props;
 
    
   

     return (
    
      <div>
           <div className={styles.row}>
                <button
                  className={styles.button}
                  aria-label="Increment value"
                  onClick={actions.increment}  
                >
                +
                </button>
                
                <span className={styles.value}>{ countValue }</span>
                
                <button
                  className={styles.button}
                  aria-label="Decrement value"
                  onClick={actions.decrement}
                >
                 -   
                </button>
           </div>
     </div>

          )

     }
        

export default CountN

Затем я использую контейнер для передачи данных в CountN

Контейнер ниже:

import React from 'react';
import CountN from "../../components/countN"

import { connect } from 'react-redux'
import * as CountActions from '../../actions'
import { bindActionCreators } from 'redux';

const mapStateToProps = (state) =>({
       countValue: state.value
})

const mapDispatchToProps = (dispatch) =>({
       actions: bindActionCreators(CountActions,dispatch)
})


export default connect(
     mapStateToProps,
     mapDispatchToProps
)(CountN)

И для управления состояниями я создаю Reducer для установки состояний:

Reducer ниже:

import * as types  from '../constants/CountTypes';

const initialState = [{
    value: 0,
    payload: 0,

}]

 const counter = (state=initialState,action)=> {
    switch (action.type){
        case types.Increment:
            return [{
                value: state.value + 1,
                payload: 0,
            }]
        case types.Decrement:
            return [
                ...state,
                {
                    value: state.value - 1
                }
          
            ]
        case types.IncrementByAmount:
            return [{
                value: state.value + action.payload ,
                payload: action.payload
            }     
            ]
        default:
            return state
    
    }
};

export default counter;

Плюс, я создаю магазин с "CreateStore (reducer)" для хранения данных,

Теперь проблема в том, что я получаю сообщение об ошибке:

TypeError: Невозможно прочитать свойство «приращение» неопределенного значения

Я понимаю, что состояние не определено,

Может ли какой-нибудь эксперт помочь мне выяснить, какая часть неверна, почему данные убежища не было передано в контейнер через "props" ???

Большое спасибо

1 Ответ

0 голосов
/ 03 августа 2020

Код, который у вас есть, должен работать, но я внес некоторые изменения в состояние, вы определили его как массив, но я не вижу причины, по которой я изменил его на объект. Ваш mapStateToProps не считает состояние массивом, поэтому это могло быть ошибкой. См. Комментарии в коде ниже, где я внес изменения.

const { Provider, connect } = ReactRedux;
const {
  createStore,
  applyMiddleware,
  compose,
  bindActionCreators,
} = Redux;

//I changed initialState to an object instead of an array
const initialState = {
  value: 0,
  payload: 0,
};
//action types
const types = {
  Increment: 'Increment',
  Decrement: 'Decrement',
  IncrementByAmount: 'IncrementByAmount',
};
//action creators
const CountActions = {
  increment: () => ({ type: types.Increment }),
  decrement: () => ({ type: types.Decrement }),
};
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case types.Increment:
      //changed to object
      return {
        value: state.value + 1,
        payload: 0,
      };
    case types.Decrement:
      //changed to object
      return {
        ...state,
        value: state.value - 1,
      };
    case types.IncrementByAmount:
      //changed to object
      return {
        value: state.value + action.payload,
        payload: action.payload,
      };
    default:
      return state;
  }
};
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(() => (next) => (action) =>
      next(action)
    )
  )
);
const CountN = (props) => {
  const { countValue, actions } = props;
  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={actions.increment}
        >
          +
        </button>
        <span>{countValue}</span>
        <button
          aria-label="Decrement value"
          onClick={actions.decrement}
        >
          -
        </button>
      </div>
    </div>
  );
};
const mapStateToProps = (state) => ({
  countValue: state.value,
});

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(CountActions, dispatch),
});

const App = connect(
  mapStateToProps,
  mapDispatchToProps
)(CountN);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>
...