Как я могу передать данные Apollo и параметры URL-адреса React Router 4 моим компонентам

Я использую реактивный маршрутизатор V4 и клиент apollo. У меня есть несколько маршрутов, которые считаются частными. У меня есть эти маршруты в отдельном компоненте. Я использую withRouter (), чтобы обернуть компонент PrivateRoute, чтобы получить весь передаваемый маршрут. Я также обертываю это в запросе graphql, чтобы знать, что пользователь вошел в систему. Моя проблема в том, что я не могу получить и данные из graphql, и данные маршрута.

Определяя маршрут таким образом, я получаю данные apollo, но не совпадение: id <Route exact path="/people/:id" render={() => <Person {...this.props} />} />

И если я изменю маршрут на это, я получу идентификатор params, но в моих реквизитах нет данных apollo <Route {...this.props} exact path="/people/:id" component={Person} />

Вот мой основной компонент маршрута

const Routes = () => (
  <Router>
    <div>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/login" component={Login} />
        <Route path="/create-account" component={CreateUser} />
        <PrivateRouteContainer />
      </Switch>
    </div>
  </Router>
);

Вот мои PrivateRoute и PrivateRouteContainer

class PrivateRoute extends Component {
  render() {
    if (this.props.data.loading) {
      return <Loading />;
    } else if (this.props.data.user) {
      return (
        <div>
          <VerticalNavFixed />
          <article className="docs-content">
            <Switch>
              <Route {...this.props} exact path="/people/:id" component={Person} />
            </Switch>
          </article>
        </div>
      );
    }
    return <Redirect to={{ pathname: '/login', state: { from: this.props.location } }} />;
  }
}


const PrivateRouteContainer = graphql(userQuery, { options: { fetchPolicy: 'network-only' } })(withRouter(PrivateRoute));

person JoshJoe    schedule 25.07.2017    source источник


Ответы (2)


Оказывается, на мой маршрут уже был отправлен пользователь, и это все, что мне нужно, чтобы убедиться, что маршрут безопасен. Кроме того, мне нужно обернуть мой другой компонент другим запросом, поэтому мне не нужны существующие данные запроса, передаваемые компоненту. Я пошел с этим

<Route exact path="/people/:id" render={() => <Person {...this.props} />} />

Затем в моем компоненте я обернул его переменной params в параметрах, что заставляет запрос ждать этого параметра.

export const PersonWithData = graphql(PersonQuery, {
  options: ownProps => ({ variables: { id: ownProps.match.params.id } }),
})(Person);
person JoshJoe    schedule 26.07.2017

Одно из решений - объединить свойства маршрутизатора и свойства запроса в функции React.cloneElement. В вашем случае это могло бы выглядеть так:

class PrivateRoute extends Component {
  render() {
    if (this.props.data.loading) {
      return <Loading />;
    } else if (this.props.data.user) {
      return (
        <div>
          <VerticalNavFixed />
          <article className="docs-content">
            <Switch>
              <Route path="/people/:id" render={(props) => {return React.cloneElement(<Person />, {user: this.props.data.user, ...props})}} />
            </Switch>
          </article>
        </div>
      );
    }
    return <Redirect to={{ pathname: '/login', state: { from: this.props.location } }} />;
  }
}


const PrivateRouteContainer = graphql(userQuery, { options: { fetchPolicy: 'network-only' } })(withRouter(PrivateRoute));

person Locco0_0    schedule 26.07.2017
comment
Спасибо, я также опубликовал решение, с которым пошел. Я хочу пока не использовать React.cloneElement. - person JoshJoe; 28.07.2017