Skip to content

Latest commit

 

History

History
106 lines (82 loc) · 6.12 KB

redux.md

File metadata and controls

106 lines (82 loc) · 6.12 KB

Redux workshop tutorial

Pre homework:

https://code-cartoons.com/a-cartoon-intro-to-redux-3afb775501a6#.x0u45w69v

Docs:

Redux: http://redux.js.org/index.html

Tutorial

Step 1

Let’s start from reduxifing toggling basic info from enroll view (src/components/enroll/BasicInfo). We want to change toggleForm to use redux.

  1. Install locally package redux and react-redux (npm install --save). Install 1.0.0 version of redux-router.

  2. Read this doc and:

  • change related action in EnrollActionCreator to just return action data
  • notice type vs actionType difference
  • change BasicInfo component to dispatch action manually (assume for now that you have dispatch in props)
  • you can remove all code related to subscribing to the store changes
  1. But of course we need to have this dispatch from somewhere. Read this react-redux doc and:
  • use connect method in your BasicInfo component.
  • implement mapStateToProps as empty for now
  1. Read reducers doc and create EnrollReducer in a directory named reducers. 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 on Object.assign doc. Notice that you should set initial state here, instead of doing this in your component's contructor.

  2. Let's create a store:

  1. Now you can implement mapStateToProps in BasicInfo 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 instead this.state.open in the component body

Step 2

Do the same for toggleForm in src/enroll/Preferences.js

Step 3

Reduxify src/containers/Participants.js (there is setState in componentWillMount)

Step 4

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.

Step 5

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 from redux
  • create store in application.js (take a look on client.js description - note intialState 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 leave initialState as empty hash for now
  • see this part for how to inject __INITIAL_STATE__ that we are already using in application.js to set initialState 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.

Step 6

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 - for Partitipants.js:
    • method should be static
    • method should take dispatch and params as arguments
    • dispatch action requesting students there (using dispatch from arguments)
    • use this method in componenentWillMount
  • In server.js, use Promise.all to wait for all the promises returned by fetchAll 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