Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
712 views
in Technique[技术] by (71.8m points)

reactjs - What are your best practices for preloading initialState in your Redux apps?

I'm currently not happy with the hacks I've come up with using Flux, and now Redux for populating initialState in my store.

I always send a payload of JSON down with the initial page load. Universal JavaScript is not an option in some of my applications as they are not all backed by Node. I would like to focus on "best practices" and patterns around how the data is preloaded on the client. Then, I feel that moving to the server is trivial.

Here’s a gist of what I’m currently doing at work and in a few other toy apps using Redux:

https://gist.github.com/kevinold/5767bb334472b7e2bfe3

To summarize:

  • I’m sending global variables down with the page
  • In componentDidMount() I'm dispatching actions that “receive” and handle the various pieces of data. (These “receive” methods are used when processing these bits of data when they are fetched async via a request action, and I’m repurposing them here since I already have the data.)

This works and there aren’t any issues that we’re running into, but it feels like a hack I’m not really happy with. Also, I feel that the initial state of Redux isn’t happy with me doing it this way.

According to http://rackt.org/redux/docs/recipes/ServerRendering.html and the section “The Client Side”, I am able to pass initialState to my store.

Here’s a patch I have for another project I'm helping with (KeystoneJS). I'm passing it's Keystone object into the initialState:

https://github.com/kevinold/keystone/commit/6f80c2f6f1e5c081361369a8bb31b75f1e62460f#diff-cd8e9933209e834b0519a0257bcfa914R8

While that does work, as you can see, I’m forced to match the shape of the output of my overall combinedReducers (https://github.com/kevinold/keystone/commit/6f80c2f6f1e5c081361369a8bb31b75f1e62460f#diff-b4b498ca92c4d05e050b45c725c26f9d) or I will get console warnings, etc.

I might be extremely lazy in dealing with this, but trying to limit having to update another piece of data when I add/change anything related to reducers (add a reducer, how they are composed, etc.).

I realizing I might have to in order to get this initialState into the reducers properly.

I'm currently digesting how (https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/client.js#L25) handles it's initialState.

I’d really appreciate some feedback on "best" and "real world" practices that are working for others.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don’t fully understand the question but I’ll try my best to answer.

In componentDidMount() I'm dispatching actions that “receive” and handle the various pieces of data. (These “receive” methods are used when processing these bits of data when they are fetched async via a request action, and I’m repurposing them here since I already have the data.)

This is a bad place to dispatch them. If you choose to dispatch actions instead of prodiving initial state directly, do that before rendering. In other words, do that right after creating the store! This way you don’t render the initial blank state.

While that does work, as you can see, I’m forced to match the shape of the output of my overall combinedReducers (https://github.com/kevinold/keystone/commit/6f80c2f6f1e5c081361369a8bb31b75f1e62460f#diff-b4b498ca92c4d05e050b45c725c26f9d) or I will get console warnings, etc.

You’re not supposed to create the initialState object manually. You’re supposed to create a Redux store on the server, dispatch actions there to prefill it with data, and when it’s ready, call store.getState() to retrieve the state you want to pass down to the client. On the client, you’d read it from a global variable, and create the client store instance with it. In other words you never have to manually create initialState—you’re supposed to grab it on the server with store.getState(), pass it to client, and create a store with it.

Therefore I don’t understand the problem you describe. If your reducer names or nesting changes, it will change on the server too. There is nothing you need to do to “fix it”—if you use Redux both on client and server, their state structure will match.

I’d really appreciate some feedback on "best" and "real world" practices that are working for others.

  1. If you use Redux on server, prefill the store as described above, and pass its state down to the client. In this case you need to use the initialState argument of createStore().

  2. If you for some reason don’t use Redux on server but you want to prefill the data anyway (e.g. maybe you use something other than Node), the approach with dispatching actions is your next best bet because it doesn’t require your backend to know the state shape. In this case, you should pass those actions as JSON to the client, and dispatch() all of them right after the store is created.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...