vorahkas
@vorahkas
Люблю интерфейсы. Использую ReactJS

Как выполнить action до рендеринга с сервера?

Имеется приложение react + redux с серверным рендерингом.
В нем есть компонент в который выводится список пользователей получаемый с api.
Action для запроса к api вызывается с помощью componentWillMount().

Сейчас получается так, что запрос к api выполняется всегда на клиенте, а хотелось бы чтобы при открытии страницы site/users с сервера приходил уже готовый html c пользователями.

Собственно вопрос: как выполнить action на сервере и отдать пользователю страницу с результатами?
  • Вопрос задан
  • 287 просмотров
Решения вопроса 1
devellopah
@devellopah
// 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));
        });
    }
  });
});


твой компонент который загружается при переходе на роут должен иметь статический метод fetchData, он может выглядеть примерно так

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
		);
	}
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы