-
-
Notifications
You must be signed in to change notification settings - Fork 15.3k
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
Merging part of state from server into initial state #433
Comments
We're firing an action as soon as the store is created for hydration which reads from sessionStorage, localStorage or other services to retrieve information. |
@merk Do I understand correctly that you do something like this:
Or do you still pass hydrated state a second argument to |
My understanding of the second argument to createStore is for state serialized from the server. The kind of information we hydrate is authentication tokens and things that should persist across reloads, nothing more. But yes, thats basically what we're doing. |
Indeed, the state from server should be passed as second argument to It will be merged with the initial state of your reducers ("stores" in 0.12) specified as default parameters. |
@gaearon
On next action dispatch state of |
Do you want to combine parts of state from server with initial state? I assumed you wanted to prefill some reducers, but not the others. In this case don't use ES6 default parameters and do this manually, or via a custom "hydrate" action. Both options are fine. |
const initialState = {
options1: [],
options2: [],
input1: "Your text",
input2: "Your text",
}
// We don't call them stores anymore! Check out 1.0 API and terminology.
// http://gaearon.github.io/redux
function reducer(state, action) {
// I want to hydrate this reducer's state with options1 and options2 with values from the server
// but at the same time I want input1 and input2 to be merged from the initialState object.
if (typeof state === 'undefined') {
// Server didn't supply any state. Use local state.
state = { ...initialState, hydrated: true };
} else if (!state.hydrated) {
// Server supplied state, but it's not merged with our local initial state yet.
state = { ...initialState, ...state, hydrated: true };
}
// do something
return state;
} Another way of writing the same code: const initialState = {
options1: [],
options2: [],
input1: "Your text",
input2: "Your text",
}
function reducer(state = initialState, action) {
if (!state.hydrated) {
state = { ...initialState, ...state, hydrated: true };
}
// do something
return state;
} |
@gaearon Thanks, adding an extra flag seems to be the best way! Really appreciate your help. |
I feel like merging state should be the default. |
This is exactly how it works when you use |
@gaearon Are you saying to put the server state in combineReducers instead of in createStore like the examples show? |
The code is in this thread is from the times when Redux 1.0 wasn’t even a thing 😄 . This works fine today: const a = (state = 5, action) => state
const b = (state = 10, action) => state
const reducer = combineReducers({ a, b })
const store = createStore(reducer, { a: 42 })
console.log(store.getState()) // { a: 42, b: 10 } |
Also, I wrote above that merging “just works” when you use @roganov wanted something more sophisticated:
By default |
You sure about that? |
Yes, I am sure about that. 😉 |
Let's consider the following snippet:
I want to hydrate this store with
options1
andoptions2
with values from the server, but at the same time I wantinput1
andinput2
to be merged from theinitialState
object.It would've been easy to subscribe to the
'@@INIT'
action and do the initialization I need, but since it's been explicitly said (#186) that this is an anti-pattern I've ruled this option out.Two other options I've come up with:
input1
andinput2
are defined:But this is very hacky and someone else is going to ask why this check is there.
2) Modify initial state that comes from the server before passing it as a second argument to
createRedux
.Probably better, but I'd like to keep initial state in the reducer's module.
What is the preferred way to achieve what I want? I keep thinking that there should be something like '@@hydrate' action where we can do initialization.
The text was updated successfully, but these errors were encountered: