https://code-cartoons.com/a-cartoon-intro-to-redux-3afb775501a6#.x0u45w69v
Redux: http://redux.js.org/index.html
Let’s start from reduxifing toggling basic info from enroll view (src/components/enroll/BasicInfo).
We want to change toggleForm to use redux.
-
Install locally package
reduxandreact-redux(npm install --save). Install 1.0.0 version ofredux-router. -
Read this doc and:
- change related action in
EnrollActionCreatorto just return action data - notice
typevsactionTypedifference - change
BasicInfocomponent to dispatch action manually (assume for now that you havedispatchinprops) - you can remove all code related to subscribing to the store changes
- But of course we need to have this dispatch from somewhere. Read this react-redux doc and:
- use
connectmethod in yourBasicInfocomponent. - implement
mapStateToPropsas empty for now
-
Read reducers doc and create
EnrollReducerin a directory namedreducers. Have in mind, that it's good practise to have reducers as pure functions. It means they are suppose to return new state merged with old one, instead of just modifing old one. Take a look onObject.assigndoc. Notice that you should set initial state here, instead of doing this in your component'scontructor. -
Let's create a store:
- Read redux doc and create your new store. You will need also to read about combining reducers to get this fully working.
- Then read react-redux doc and use the store in
application.js.
- Now you can implement
mapStateToPropsinBasicInfocomponent:
- from the global state, pick what your component needs to have in it's local state (
open) - remember how you named key for related reducer while creating a store - state you want to pick is namespaced with this name
- use
this.props.openinsteadthis.state.openin the component body
Do the same for toggleForm in src/enroll/Preferences.js
Reduxify src/containers/Participants.js (there is setState in componentWillMount)
In real world API is not synchronious, we don't get data right away. Checkout to REDUX4-pre tag, where we have changed getStudents method from API to work asynchroniously (like a real world API).
But our participants view broke, so we need to fix it.
- Read
redux-thunkdoc and set it up. - Here is more info how to adjust action creator.
Checkout to tag REDUX5-pre.
Read this documentation and try to use it in our server.js.
Tips:
- change store.js to define and export function to configure store istead of just exporting store.
- this funciton should take initialState and pass it to
createStorefromredux - create store in
application.js(take a look onclient.jsdescription - noteintialStatetaken from window, but we will get back to this later. - open
server.jsand do similar thing there - see handling request part of the doc - you can leaveinitialStateas empty hash for now - see this part for how to inject
__INITIAL_STATE__that we are already using inapplication.jsto setinitialStatefor the store
We are almost there Restart server and check page source. Notice that you can see component tree, but you don't see any data there.
It's because data for the server side are fetched asynchroniously on client side and fetching finishes after server renders the page. So all we need is to fetch data also server side and wait with rendering the page for fetch to finish.
- Paste this method to your
server.js:
function fetchAll(store, renderProps) {
return renderProps.components.map((componentClass) => {
if (componentClass.fetchData) {
return componentClass.fetchData(store.dispatch, renderProps.params)
}
});
}- This will return an array with promises - components that match the current route will be mapped to their
fetchDatamethod, which is suppose to return promise - We don't have
fetchDatamethod in the componente, so let's add one - forPartitipants.js:- method should be static
- method should take
dispatchandparamsas arguments - dispatch action requesting students there (using
dispatchfrom arguments) - use this method in
componenentWillMount
- In
server.js, usePromise.allto wait for all the promises returned byfetchAllmethod and render html only after all promises are resolved. - And the last thing is that we need configure
redux-router(it's already installed)- use this code to configure the store:
export function configureStore(reduxReactRouter, createHistory, initialState = {}) { const createStoreWithMiddleware = compose( applyMiddleware(thunk), reduxReactRouter({ routes, createHistory }) )(createStore); return createStoreWithMiddleware(reducers, initialState);
}
* take a look on [client](https://github.com/acdlite/redux-router/blob/master/examples/server-rendering/client.js) and [server](https://github.com/acdlite/redux-router/blob/master/examples/server-rendering/server.js) examples and configure `redux-router` it in our application