@Void117

React.js. Доставка данных с сервера при первой загрузке и обновлении роута. Есть ли какие-то паттерны?

Что есть сейчас: CRA, react-router v4. Пока что у меня есть window.__initialData с массивом данных для редукс-стора прямо в html, отсюда берутся изначальные данные довольно общего характера, например, статус пользователя или данные для шапки/футера. Стоит ли сюда же заворачивать данные о компонентах каждой страницы?
Что должно происходить при переходе по роуту? Как-то блокировать переход, отправлять запрос на сервер о списке компонентов, обновлять стор и после этого начинать рендерить новую страницу?

В общем, для меня не очень понятно, какие вообще есть подходы. Очевидно, что можно делать запрос от отдельного компонента, но если сложится ситуация когда необходимо будет отправить 10 запросов, то из-за разницы в скорости ответов и длительности рендеринга, может сложится ситуация где порядок отображения на мгновение будет нарушен. В общем этот способ выглядит слишком не синхронным и не оптимизированным.

Буду рад если кто-то поделится ссылкой на статью с разбором подобного вопроса.
  • Вопрос задан
  • 2333 просмотра
Пригласить эксперта
Ответы на вопрос 1
@SuperOleg39ru
Front-end разработчик
У меня аналогичная ситуация, настраиваю react-router для нового приложения. Сразу скажу, что паттернов, кроме документации, не попадалось)

В initialState для store вы сами решаете, что надо туда добавлять, в любом случае каждый редьюсер дает свой дефолтный кусочек общего state.

По переходам - разделите данные на общие, которые нужны до старта приложения, и конкретные для компонентов.

Про блок перехода - пример из документации, в зависимости от данных сверху, роут либо рендерит компонент, либо делает редирект.
const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)


Пример компонента, который запрашивает данные. Все свойства через connect, но вы можете так же менять и отслеживать состояние запроса в state.
// getUsers - свойство из mapDispatchToProps, запрос на сервер, по завершению обновляет users в вашем Store
// users - свойство из mapStateToProps
class UserListContainer extends Component {
  componentWillMount() {
    this.props.getUsers();
  }

  render() {
    const { users } = this.props;

    if (!users) {
      return <Spinner />
    }

    return <UserList data={users} />
  }
}


В моем приложении я включаю spinner при старте приложения, и выключаю в компоненте, который рендерится после получения нужных данных. Например можно делать так (свойства и методы так же через connect).
У вас будет крутиться прелоадер, пойдет запрос на токен, по успеху пойдет запрос на users, по успеху начнет рендериться UserListContainer, который должен выключить прелоадер.
class App extends Component {
  render() {
    const { appIsReady } = this.props;

    // наш лоадер на весь экран при appIsReady: false
    return (
        <div>
          {!appIsReady && <Spinner style='fullscreen' />}
          </Switch>
            <Route path='/' exact={true} component={Home} />
            <Route component={NotFound} />
          <Switch>
        </div>
    );
  }
}

class Home extends Component {
  componentWillMount() {
    if (!this.props.token) {
      this.props.getToken();
    }
  }

  render() {
    const { token } = this.props;

    if (!token) {
      return null;
    }

    // UserListContainer в willMount меняет appIsReady на true
    return <Route path='/users' component={UserListContainer} />  
  }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы