rt2zz / redux-persist-immutable

Redux Persist Immutable
MIT License
114 stars 31 forks source link

state.forEach is not a function #16

Closed xcarpentier closed 5 years ago

xcarpentier commented 7 years ago

Hello, I have this error: simulator screen shot 12 nov 2016 23 01 30

My store is configure like that:

import { createStore, applyMiddleware } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist-immutable';
import { AsyncStorage } from 'react-native';

import createSagaMiddleware from 'redux-saga';

import middleware from 'Middlewares';
import reducers from 'Reducers';
import sagas from 'Sagas';

const sagaMiddleware = createSagaMiddleware();

const createStoreWithMiddleware = applyMiddleware(...middleware, sagaMiddleware)(createStore);

const configureStore = () => {
  const store = autoRehydrate()(createStoreWithMiddleware)(reducers);
  persistStore(store, { storage: AsyncStorage });
  sagaMiddleware.run(sagas);
  return store;
};

My reducer like that:

/*
 * @providesModule UserReducer
 */

import Immutable from 'immutable';

const initialState = Immutable.Map({
  id: null,
  name: null,
  email: null,
});

export default function user(state = initialState, action) {
  if (action.type === 'USER_FETCH_SUCCEEDED') {
    return Immutable.Map({ ...state, ...action.user });
  }
  return state;
}

Do you have any idea about this issue ?

rt2zz commented 7 years ago

looks correct, possibly autorehydrate is not being applied

algbeta commented 7 years ago

@rt2zz @xcarpentier I've been struggling with the same issue. If I understand it correctly when we are using redux-persist-immutable and redux-persist in createPersistor.js we are having those variables

  var stateIterator = config._stateIterator || defaultStateIterator;
  var stateGetter = config._stateGetter || defaultStateGetter;
  var stateSetter = config._stateSetter || defaultStateSetter;

overriden from config:

function _stateIterator(state, callback) {
  return state.forEach(callback);
}
function _stateGetter(state, key) {
  return state.get(key);
}
function _stateSetter(state, key, value) {
  return state.set(key, value);
}

But the thing is stateIterator, stateGetter and stateSetter are used for current state which is got by store.getState() and since I'm using combineReducers I get plain object instead of immutableJs one.

Here is a note from redux tutorial

The resulting reducer calls every child reducer, and gathers their results into a single state object. The shape of the state object matches the keys of the passed reducers. Consequently, the state object will look like this:

{
 reducer1: ...
 reducer2: ...
}

So I believe those stateIterator, stateGetter and stateSetter should be used on inner ImmutableJs objects but not on the object returned by store.getState().

fengerzh commented 7 years ago

I got exactly same error here. Is there any workaround to bypass this error?

kbaird5 commented 7 years ago

Using this code, I was getting the 'state.forEach' is not a function error. Now, I seem to get 'state.has' is not a function error. I assume these errors are related to having immutablejs just on substate instead of the full state. I verified that using a single state works. What is the magic to get multiple substates to work? Thanks.

const combinedReducers = combineReducers(
    {
        subStateA: stateAReducer,
        subStateB: stateBReducer
    }
);

// combine initial state here; or set as default value on reducer which will be loaded when the reducer is
const combinedInitialState = {
    subStateA: fromJS(subStateBInitialData),
    subStateB: fromJS(subStateBInitialData)
};

const store = createStore(combinedReducers, combinedInitialState, composeEnhancers(middleware, autoRehydrate()));

persistStore(store);
tocttou commented 6 years ago

Same error here.

diegolaciar commented 6 years ago

The same error , anyone have a workaround for this issue ?

basitsattar commented 6 years ago

Any update?

ghost commented 5 years ago

I got the error too, and I resolved it by using:

// Array.prototype.forEach.call(state, (key: PropertyKey) => {
[].forEach.call(state, (key: PropertyKey) => {
  // do something...
});

or this:

Object.keys(state).map((key: PropertyKey) => {
  // do something...
});

I think it is because state is an Array-like object, maybe.. :)

michaelcuneo commented 5 years ago

@xcarpentier any idea what @ghost meant by the resolution that he came up with... I can't see any code even resembling this in any parts of Immer / Redux-persist-immutable, etc... Where did he place this fix?