Ilja Ilja - 3 months ago 49
React JSX Question

Use immutable js to set reducer state to returned array

I have a simple reducer example:

import { fromJS } from 'immutable'
import {
REQUEST_SUCCESS
} from './constants'

const initialState = fromJS({
badges: []
})

function badgesReducer (state = initialState, action) {
switch (action.type) {
case REQUEST_SUCCESS:
return state
.set('badges', action.payload.badges || [])
default:
return state
}
}

export default badgesReducer


Idea here is to set badges equal to array returned by api response that is within
action.payload.badges
however I believe I am doing something wrong as I get following error returned:


warning.js:44 Warning: Failed prop type: Invalid prop
badges
of type
object
supplied to
Badges
, expected
array


Answer

The error is occurring because react is expecting an array but you're returning an Immutable.List. And React renders the component twice because the first render happens with reducer initialState and then the second render is caused due to props change (after the dispatched action).

Your props are inconsistent since you are passing Immutable.List in initialState & array in REQUEST_SUCCESS action.

If you want to stick with Immutable.js everywhere, then declare propTypes like this.

Component

import React, { PropTypes } from 'react'
import { List } from 'immutable'

Component.propTypes = {
  badges: PropTypes.instanceOf(List)
}

Reducer

import { fromJS, List } from 'immutable'

function badgesReducer (state = initialState, action) {
  switch (action.type) {
    case REQUEST_SUCCESS:
      return state
        .set('badges', fromJS(action.payload.badges) || List())
    default:
      return state
  }
}

And if you want to always pass an array to the component, remove fromJS from the initialState declaration