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
redux
andreact-redux
(npm install --save
). Install 1.0.0 version ofredux-router
. -
Read this doc and:
- change related action in
EnrollActionCreator
to just return action data - notice
type
vsactionType
difference - change
BasicInfo
component to dispatch action manually (assume for now that you havedispatch
inprops
) - 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
connect
method in yourBasicInfo
component. - implement
mapStateToProps
as empty for now
-
Read reducers doc and create
EnrollReducer
in 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.assign
doc. 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
mapStateToProps
inBasicInfo
component:
- 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.open
insteadthis.state.open
in 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-thunk
doc 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
createStore
fromredux
- create store in
application.js
(take a look onclient.js
description - noteintialState
taken from window, but we will get back to this later. - open
server.js
and do similar thing there - see handling request part of the doc - you can leaveinitialState
as empty hash for now - see this part for how to inject
__INITIAL_STATE__
that we are already using inapplication.js
to setinitialState
for 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
fetchData
method, which is suppose to return promise - We don't have
fetchData
method in the componente, so let's add one - forPartitipants.js
:- method should be static
- method should take
dispatch
andparams
as arguments - dispatch action requesting students there (using
dispatch
from arguments) - use this method in
componenentWillMount
- In
server.js
, usePromise.all
to wait for all the promises returned byfetchAll
method 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