Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add store.resetState for reverting to initial state value #658

Closed
wants to merge 1 commit into from

Conversation

tgriesser
Copy link

I have a situation where I'd like to reset the entire app state to the original value (after ActionTypes.INIT is run), but couldn't find a clean way to write it as a plugin without replacing the majority of createStore.

I can also imagine situations where you'd want to replace the entire currentState with a new value, for example if you wanted to re-hydrate the entire app state from a different serialized session.

So I wanted to see if this resetState or an alternate more generic replaceState seemed like a good enough use case to add to the core API. The replaceState would look similar to this PR, but would pass in the state value and then run the init dispatch:

/**
 * Replaces the state tree with a new value and runs "INIT"
 *
 * @returns {void}
 */
function replaceState(newState) {
  currentState = newState;
  dispatch({ type: ActionTypes.INIT });
}


// When a store is created, an "INIT" action is dispatched so that every
// reducer returns their initial state. This effectively populates
// the initial state tree.
replaceState(initialState);

@alkhe
Copy link
Contributor

alkhe commented Aug 30, 2015

We do this in fluxette.

@gaearon
Copy link
Contributor

gaearon commented Aug 31, 2015

I don't think there is a need for this in core.

Store API must be as simple as possible so it's easy to write extensions like Redux DevTools.
Even one method is a huge addition.

See how to implement this in userland:

function makeHydratable(reducer, hydrateActionType) {
  return function (state, action) {
    switch (action.type) {
    case hydrateActionType:
      return reducer(action.state, action);
    default:
      return reducer(state, action);
    } 
  }
}

Usage:

const HYDRATE_STATE = 'HYDRATE_STATE';
const reducer = combineReducers(myReducers);
const hydratableReducer = makeHydratable(reducer, HYDRATE_STATE);
const store = createStore(hydratableReducer, initialState);

// later
store.dispatch({
  type: HYDRATE_STATE,
  state: initialState
});

@gaearon gaearon closed this Aug 31, 2015
@gaearon gaearon mentioned this pull request Aug 31, 2015
@tgriesser
Copy link
Author

I assume you'd need to also dispatch({type: ActionTypes.INIT}) to re-init any of the reducers which aren't covered in the hydrate state?

@gaearon
Copy link
Contributor

gaearon commented Aug 31, 2015

Right!

@gaearon
Copy link
Contributor

gaearon commented Aug 31, 2015

Oh wait, you wouldn't need to. Just pass action.state to root reducer.

@gaearon
Copy link
Contributor

gaearon commented Aug 31, 2015

Here's the fixed version:

function makeHydratable(reducer, hydrateActionType) {
  return function (state, action) {
    switch (action.type) {
    case hydrateActionType:
      return reducer(action.state, action);
    default:
      return reducer(state, action);
    } 
  }
}

@tgriesser
Copy link
Author

Awesome, so obvious now!

@vicentedealencar
Copy link

@gaearon I don't see a reason to call the reducer when the action is hydrateActionType, I don`t think any reducer should handle this action. I understand that the reducers would all ignore it and return state as is, so why not short-circuit the reducer returning action.state?

I am probably missing something, but I have it implemented this way..

@gaearon
Copy link
Contributor

gaearon commented Sep 1, 2015

I understand that the reducers would all ignore it and return state as is, so why not short-circuit the reducer returning action.state?

The author wanted to be able to specify non-full state, and have reducers return initial state in this case: #658 (comment).

@catamphetamine
Copy link

@tgriesser Why would you do this:

function replaceState(newState) {
  currentState = newState;
  dispatch({ type: ActionTypes.INIT });
}

Instead of this:

function resetState() {
  currentState = {};
  dispatch({ type: ActionTypes.INIT });
}

What's the point of currentState = newState when it's gonna be overridden with the initial reducer state leaves anyway, so the new state is just gonna be the combined initial state.
Perhaps to store some non-reduceable data in the state tree but I don't see a motivation for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants