Wednesday, 24 May 2017

Setting initialState in reducer asynchronously

I have a react app that I am trying to generate routes based on data that is called from redis cache.

I am using https://github.com/ayroblu/ssr-create-react-app-v2

I have a route component which loops through this.props.pages and creates the routes like so:

class Routes extends Component {

  getRoutes(){
    let container = null;
    const routes = []

    /**
     *  We use a switch statement because the Routes component 
     *  attribute wont take a string so we need to call
     *  the object that we import i.e. HomePage
     */ 
    forEach(this.props.pages, page => {
      switch(page.template){
        case 'home':
          container = HomePage 
          break;
        case 'about':
          container = AboutPage 
          break;
        default:
          throw new Error("No page container matching page's template")
          return;
      }

      routes.push(<Route path={`${page.path}`} component={container} key={key}/>)
    })

    return routes;

  }

  render() {
    return (
      <Switch>
        {this.getRoutes()}
        <Route component={NoMatch}/>
        }
      </Switch>
    )
  }
}

I have a page reducer which fetches the page data for the routes asynchronously from the redis cache which looks like this:

import { SET, RESET } from '../types/page'
import getInitialState from './../../server/initialState'

async function getInitialStateFromCache() {
    const initialState = await getInitialState();

    const {pages} = initialState[0]

    return pages
}

const initialState = getInitialStateFromCache()


export default function reducer(state=initialState, action) {
  switch (action.type) {
    case SET:
      return Object.assign({}, state, action.payload)
    case RESET:
      return {...initialState}
    default:
      return state
  }
}

When the first render is called in my route component, this.props.pages is undefined so the requested page 404's but then the second render in the client, it appears. This means that when I view page source, the content hasn't been server side rendered.

How can I delay the first render so that this.props.pages is defined when I need it?



via Stretch0

No comments:

Post a Comment