Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

combineReducers destroys Redux state and also breaks multi ImmutableJs reducers

Tags:

Banging my head on this. I've blown through the typical ReactJS and Redux app tuts and am working on my own app. The problem is when using combineReducers() to create a single reducer for the Redux store. I currently have three reducers which, on their own, work fine when when added as the reducer param for createStore(). The first reducer holds all of my actions and is called:

HeaderReducer

import { isActive } from '../actions/HeaderActions';

export const initialButtonState = {
  isActive: false,
  invertStyles: false
}

export default (state = initialButtonState, action) => {
  switch (action.type) {
    case 'SET_ACTIVE':
      return {
        ...state,
        isActive: action.isActive(state),
        invertStyles: action.invertStyles(state),
      }

    default:
      return state
  }
}

The second and third reducer are built using ImmutableJS to propagate some dummy content for separate lists. Again, individually these reducers work on their own but do not when combineReducers() combines them. The second reducer file is called:

ListItems

import Immutable from 'immutable';

const messagesList = Immutable.List(['9:00AM - 9:30AM','10:30AM -     11:30AM','11:45AM - 12:30PM','1:00PM - 2:15PM','3:00PM - 4:00PM']);

export default (state = messagesList, action) => {
  switch(action.type) {
    case 'addItem':
      return state.push(action.item)
    case 'deleteItem':
      return state.filter((item, index) => index !== action.index)
    default:
      return state
  }
}

The third file is called:

QuotesList

import Immutable from 'immutable';

const quotesList = Immutable.List(['Company A: 100.00$','Company B:     200.00$','Company C: 300.00$','Company D: 400.00$','Company E: 500.00$<']);

export default (state = quotesList, action) => {
  switch(action.type) {
    case 'addItem':
      return state.push(action.item)
    case 'deleteItem':
      return state.filter((item, index) => index !== action.index)
    default:
      return state
  }
}

I have all files exported via an index.js within the reducers folder:

index.js

export { default as HeaderReducers } from './HeaderReducers';
export { default as ListItems } from './MessageList';
export { default as QuotesList } from './QuotesList';

and then called in to create my store in:

Store.js

import { createStore, combineReducers } from 'redux';
import * as reducers from '../reducers';
// import HeaderReducers from '../reducers/HeaderReducers';
// import ListItems from '../reducers/MessageList';
// import QuotesList from '../reducers/QuotesList';

// let reducer = combineReducers({ ListItems: ListItems, quotes:     QuotesList})

// export default createStore(ListItems)

const reducer = combineReducers(reducers);
export default createStore(reducer);

Logging the state of the store at launch returns an Object or List, depending on the reducer I use. When I run them through combineReducer(), I get a single Object returned holding each reducer together. What breaks immediately is a .map function I have setup in ListItems.js

import React from 'react';
import { connect } from 'react-redux';
import NewItem from './NewItem';
import { addItem, deleteItem } from '../../../actions/HeaderActions';
    const ListItems = ({ListItems, dispatch}) => (
      <div>
        <ul>
          {ListItems.map((ListItem, index) => <li><span key={index}>    {ListItem} <button onClick={e => {
            dispatch(deleteItem(index))
          }}>X</button></span></li>)}
        </ul>

        <NewItem />
      </div>
    )
function mapStateToProps(ListItems) {
  return {
    ListItems,
  }
}
export default connect(mapStateToProps)(ListItems)

Console shows "_ListItems.map is not a function". I've gone through and tried editing the mapStateToProps return value but I'm grasping at straws. Thanks for reading this. Any help is definitely appreciated.

like image 906
DaneTheory Avatar asked Apr 05 '16 07:04

DaneTheory


People also ask

What does combineReducers do in Redux?

The combineReducers helper function turns an object whose values are different reducing functions into a single reducing function you can pass to createStore .

Can Redux have multiple reducers?

Having multiple reducers become an issue later when we create the store for our redux. To manage the multiple reducers we have function called combineReducers in the redux. This basically helps to combine multiple reducers into a single unit and use them.

Why we should not mutate state in Redux?

There are several reasons why you must not mutate state in Redux: It causes bugs, such as the UI not updating properly to show the latest values. It makes it harder to understand why and how the state has been updated. It makes it harder to write tests.

What happens when Redux state changes?

The only way to update a state inside a store is to dispatch an action and define a reducer function to perform tasks based on the given actions. Once dispatched, the action goes inside the reducer functions which performs the tasks and return the updated state to the store. This is what Redux is all about.


1 Answers

combineReducers doesn't support immutable. Try redux-immutable combineReducers instead.

like image 121
Ori Drori Avatar answered Sep 28 '22 03:09

Ori Drori