takayoshi
takayoshi

Reputation: 2799

Server Side Rendering React Router + Redux load data when entering route

I'm using React Router with Redux with server rendering. I have component that will fetching data from remote api, so I need wait for loading at server side, when making server side rendering

I've used this solution

https://github.com/bananaoomarang/isomorphic-redux

server.jsx

    ... after matching route, creating storage etc. wait for all needed promises completed ...

     fetchComponentData(store.dispatch, renderProps.components, renderProps.params)
      .then(renderView)

shared/lib/fetchComponentData.jsx

export default function fetchComponentData(dispatch, components, params) {
  const needs = components.reduce( (prev, current) => {

    return current ? (current.needs || []).concat(prev) : prev;
  }, []);

  const promises = needs.map(need => dispatch(need(params)));

  return Promise.all(promises);
}

and component that I wrote myself was

export default class ListComponent extends React.Component {
    static needs = [
        loadSomeData
    ]

    render() {
        return (
            <div>

            </div>
        );
    }
}

My routes.js was

export default (store) => {


return (<div>
    <Route path='/'>
        <IndexRoute component={AnotherComponent}/>
        <Route path="component" component={Component}/>
    </Route>
</div>);
};

So, the flow works good.

1) I go to /component by typing this in browser

2) Server.js calls fetchComponentData

3) fetchComponentData determines that component need load data before rendering, dispatch action with promise

4) wait promise for completed

5) render component and give this as html

But there is a problem. When I go to component from another by calling browserHistory.push('/component') data was not loading at all

I try to decide this by modifiying routes.js in such way

export default (store) => {

const loadData = (nextState, replace, cb) => {
    store.dispatch(loadSomeData());
    cb();
};


return (<div>
    <Route path='/'>
        <IndexRoute component={AnotherComponent}/>
        <Route path="component" component={Component} onEnter={loadData}/>
    </Route>
</div>);
}; 

But I've got another problem server give me rendered html and client call loadData again

So my question is how to avoid calling onEnter on client for the first time rendering on client?

Thank you for answers!

Upvotes: 0

Views: 414

Answers (1)

JAYBEkster
JAYBEkster

Reputation: 790

I propose problem here is affected by invoking routes.js on both clienside and serverside. To say it shorter: 1) there are should be 2 functions: bootstrapServer and bootstrapClient 2) bootstrapServer works well if I realized you correctly: you matches the url with a page what in your request url, dispatch data for its and render; 3) bootstrapClient should contains routes.js with onEnter - it must be invoked only on client-side

So the striking difference is that routes.js must be implemented only on clientside.

Upvotes: 0

Related Questions