D
D
Dima Morichev2015-09-01 18:51:17
JavaScript
Dima Morichev, 2015-09-01 18:51:17

How reducers process data in React Redux?

There is a problem when trying to understand the example.
Maybe the question doesn't sound right.
Maybe the error is somewhere else. But I watch it here.
Nothing comes after reducers. More precisely, as I understand, only LOAD_REQUESTED comes.
It seems like it should LOAD_OK.

function mapStateToProps(state) {
  return {
    counter: state.counter,
    app: state.app
  }
}

All listing.
store/configureStore.js
import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';

const createStoreWithMiddleware = applyMiddleware(
  thunk
)(createStore);

export default function configureStore(initialState) {
  return createStoreWithMiddleware(rootReducer, initialState);
}

reducers/index.js
import { combineReducers } from 'redux';
import counter from './counter';

const rootReducer = combineReducers({
  counter
});

export default rootReducer;

reducers/counter.js
import { LOAD_OK, LOAD_REQUESTED } from '../actions/counter';

const defaultState = {
  loading: false,
  counter: [],
  app: {},
  errors: null
};

export default function company(state = defaultState, action) {
  switch (action.type) {

    case LOAD_REQUESTED:
      return {
        loading: true
      };

    case LOAD_OK:
      return [...state, {
        loading: false,
        counter: action.counter,
        app: action.app,
        errors: null
      }];

    default:
      return state;
  }
}

containers/root.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import CounterApp from './CounterApp';
import configureStore from '../store/configureStore';
import {setCounter} from '../actions/counter'

const store = configureStore();

export default class Root extends Component {
  componentWillMount() {
    store.dispatch(setCounter());
  }
  render() {
    return (
      <Provider store={store}>
        {() => <CounterApp />}
      </Provider>
    );
  }
}

containers/CounterApp.js
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Counter from '../components/Counter';
import * as CounterActions from '../actions/counter';

function mapStateToProps(state) {
  return {
    counter: state.counter,
    app: state.app
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(CounterActions, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

components/Counter.js
import React, { Component, PropTypes } from 'react';

class Counter extends Component {
  render() {
    const { counter, app } = this.props;
    return (
      <div>
        {counter.map((item, i) =>
          <div key={i} >{item.count}</div> 
        )}
        {app.total}
      </div>
    );
  }
}

Counter.propTypes = {
  counter: PropTypes.array.isRequired,
  app: PropTypes.object.isRequired
};

export default Counter;

actions/counter.js
import request from 'axios';

export const LOAD_REQUESTED = 'LOAD_REQUESTED';
export const LOAD_OK = 'LOAD_OK';

export function setCounter() {
  return dispatch => {
    dispatch({
      type: 'LOAD_REQUESTED'
    });

    request.get(
        Routes.root_path(), {
          headers: {
            'Accept': 'application/json'
          }
        }
      )
      .then(result => {
        dispatch({
          type: 'LOAD_OK',
          counter: result.data.counter,
          app: result.data.app
        })
      })
  }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
vsuhachev, 2015-09-02
@dimaxmor

The reducer should return objects/hashes, not like you have arrays.
All this syntax { ...state, loading: true}means: Take an empty object, copy all the contents of state into it, and then override the following keys (loading, etc.)

export default function company(state = defaultState, action) {
  switch (action.type) {

    case LOAD_REQUESTED:
      return {
        ...state,
        loading: true
      };

    case LOAD_OK:
      return {
        ...state,
        loading: false,
        counter: action.counter,
        app: action.app,
        errors: null
      };

    default:
      return state;
  }
}

M
mishapsv, 2015-09-03
@mishapsv

vsuhachev you will not help to disassemble this code?
from here

case COMPLETE_TODO:
  return Object.assign({}, state, {
    todos: [
      ...state.todos.slice(0, action.index),
      Object.assign({}, state.todos[action.index], {
        completed: true
      }),
      ...state.todos.slice(action.index + 1)
    ]
  });

Why is
{ ...state, ...newState } not used all the time?
Does Object.assign({}, state, ...newState) have any special features? Seems to be similar.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question