Skip to content

Anti-pattern: reacting to @@INIT action #186

Closed
@gaearon

Description

@gaearon

In the new docs (#140) we should clarify that any actions prefixed with @@ are not meant to be handled. For example, you should never try to handle @@INIT. We might enforce that by slightly randomizing names (e.g. @@INIT_2hj3jh34).

Handling @@INIT manually will break hot reloading. It is invoked at every hot reload, so if you do your initial data transformation there, it won't work the second time.

I've seen people using @@INIT to hydrate the plain objects received from the server into the Immutable state. Instead of handling @@INIT, you need to consider one of two options:

  • convert your whole plain object state to Immutable right away before passing it to Redux;
  • check if the state is a plain object and use fromJS before handling the action.
function myReducer(state = {}, action) {
  if (!isImmutable(state)) { // some kind of typeof check here?
    state = Immutable.fromJS(state);
  }

  ...
}

It is easy to abstract this away with a createImmutableReducer function like this:

export default function createImmutableReducer(initialState, handlers) {
  return (state = initialState, action) => {
    if (!isImmutable(state)) {
      // Hydrate server plain object state
      state = Immutable.fromJS(state);
    }

    const handler = handlers[action.type];
    if (handler) {
      state = handler(state, action);
    }

    if (!isImmutable(state)) {
      throw new Error('Reducers must return Immutable objects.');
    }

    return state;
  };
}

It can then be used for creating reducers from action constant -> handler map.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions