D
D
denisftw2016-03-11 23:06:47
React
denisftw, 2016-03-11 23:06:47

How to do the initial (re-)render in the browser of a React app with Redux and ReactRouter?

I'm making an app with universal/isomorphic rendering in React. The server part is clear and works: we send some json from the backend, synchronously place it in the store, and then ReactRouter selects the desired Route and renders the correct component, returning HTML as a string.
It is not clear what to do with rendering in the browser.
All components require some data (props) to be rendered, but real data from the server can only be received asynchronously. So far I haven't come up with anything smarter than using onEnter in Route, but this approach doesn't work:

window.onload = function() {
    const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
    const store = createStoreWithMiddleware(viewPropsReducer);
    ReactDOM.render(
        <Provider store={store} >
            <Router history={browserHistory} >
                <Route path="/" component={ViewComposite} 
                     onEnter={ ({params}) => {store.dispatch(fetchViewData()); }} />
                <Route path='/admin' component={AdminComposite} 
                     onEnter={ ({params}) => {store.dispatch(fetchAdminData()); }} />
            </Router>
        </Provider>,
        document.getElementById('viewMount')
    );
};

due to the fact that by the time the promise from fetchViewData() is cut off, the rendering of the component will already have time to fail due to missing props.
In principle, it would be possible to initiate browser rendering not in window.onload, but in then() promise'a, but then it would be necessary to duplicate the logic from the Router and load its own data for each base component. Or is it just the right way?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Andrey Antropov, 2016-03-12
@Laiff

Not the most beautiful solution, but most implementations of universality work exactly like this: the state of the store is added in a serialized form into a global variable, and before rendering, the store is filled from this variable and further stretched across the components. The second aspect is dynamic data that needs to be obtained already during rendering, in this case, a common solution is to first execute all requests for obtaining such data based on the state of the router, and perform the initial rendering on resolution. The solution is not ideal with its pitfalls, but quite workable.

N
Nikita Gushchin, 2016-03-12
@iNikNik

Try https://www.npmjs.com/package/redux-async-connect
This lib will just take care of loading data when navigating through pages + is able to isomorphism.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question