D
D
Denis Sakharov2017-04-08 10:06:43
Node.js
Denis Sakharov, 2017-04-08 10:06:43

How to execute an action before rendering from the server?

There is a react + redux app with server rendering.
It has a component in which the list of users obtained from the api is displayed.
The action for the api request is called with componentWillMount() .
Now it turns out that the request to the api is always executed on the client, but I would like that when the site/users page is opened , a ready-made html with users comes from the server.
Actually the question is: how to execute an action on the server and give the user a page with the results?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Islam Ibakaev, 2017-04-08
@vorahkas

// Register server-side rendering middleware
app.get('*', (req, res) => {
  if (__DEV__) {
    webpackIsomorphicTools.refresh();
  }

   const store = configureStore();

  // If __DISABLE_SSR__ = true, disable server side rendering
  if (__DISABLE_SSR__) {
    res.send(renderHtmlPage(store));
    return;
  }

  const memoryHistory = createMemoryHistory(req.url);
  const history = syncHistoryWithStore(memoryHistory, store, {
    selectLocationState: state => state.get('routing').toJS(),
  });

  // eslint-disable-next-line max-len
  match({history: memoryHistory, routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.status(500).send(error.message);
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search);
    } else if (!renderProps) {
      res.sendStatus(404);
    } else {
      // Dispatch the initial action of each container first
      const promises = renderProps.components
        .filter(component => component.fetchData)
        .map(component => component.fetchData(store.dispatch, renderProps.params));
     
      // Then render the routes
      Promise.all(promises)
        .then(() => {
          // Using the enhanced history of react-redux-router to instead of the 'memoryHistory'
          const props = Object.assign({}, renderProps, { history });
          const content = renderToString(
            <Provider store={store}>
               <RouterContext {...props} />
            </Provider>
          );

          res.status(200).send(renderHtmlPage(store, content));
        });
    }
  });
});

your component that is loaded when going to the route should have a static fetchData method, it might look something like this
class UsersPage extends React.Component {
  
  static async fetchData(url) {
    try {
      const res = await axios.get(url);
      const users = res.data 
    } catch(err) {
      console.error(err.message);
    }
  }
  
  componentDidMount() {
    this.fetchData(url);
  }
  
  render() {
    return (
     // whatever
    );
  }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question