React Router 4 Передача реквизита в динамический компонент

У меня есть список врачей, и я пытаюсь динамически отобразить страницу с подробностями при выборе. Я вижу, что большинство людей рекомендуют передавать реквизиты через компонент Route, что-то вроде этого:

<Route path={`${match.url}/:name`}
  component={ (props) => <DoctorView doctor={this.props.doctors} {...props} />}
  />

Хотя мне не ясно, где я должен выполнять это. Я попробовал это в DoctorList и DoctorItem, но это не сработало. Итак, я установил маршрут в компоненте приложения, и я могу выбрать доктора, который затем визуализирует компонент DoctorView и отображает реквизиты match.params просто отлично. Но как мне получить данные выбранного доктора в DoctorView? Я, вероятно, делаю это сложнее, чем должно быть. Вот мой код:

App.jsx

const App = () => {
  return (
    <div>
      <NavigationBar />
      <FlashMessagesList />
      <Switch>
        <Route exact path="/" component={Greeting} />
        <Route path="/signup" component={SignupPage} />
        <Route path="/login" component={LoginPage} />
        <Route path="/content" component={requireAuth(ShareContentPage)} />
        <Route path="/doctors" component={requireAuth(Doctors)} />
        <Route path="/doctor/:name" component={requireAuth(DoctorView)} />
      </Switch>
    </div>
  );
}

DoctorList.jsx

class DoctorList extends React.Component {
  render() {
    const { doctors } = this.props;
    const linkList = doctors.map((doctor, index) => {
      return (
        <DoctorItem doctor={doctor} key={index} />
      );
    });

    return (
      <div>
        <h3>Doctor List</h3>
        <ul>{linkList}</ul>
      </div>
    );
  }
}

DoctorItem.jsx

const DoctorItem = ({ doctor, match }) => (
  <div>
    <Link
      to={{ pathname:`/doctor/${doctor.profile.first_name}-${doctor.profile.last_name}` }}>
      {doctor.profile.first_name} {doctor.profile.last_name}
    </Link>
  </div>
);

DoctorView.jsx

const DoctorItem = ({ doctor, match }) => (
  <div>
    <Link
      to={{ pathname:`/doctor/${doctor.profile.first_name}-${doctor.profile.last_name}` }}>
      {doctor.profile.first_name} {doctor.profile.last_name}
    </Link>
  </div>
);

У меня есть доступ к списку врачей через Redux, я могу подключить компонент, внести в список и сравнить идентификаторы, но это похоже на множество ненужных шагов.

2 ответа

Решение

Но как мне получить данные выбранного доктора в DoctorView?

Имейте в виду, что наличие таких путей, как /items а также /items/:id создает сценарий, в котором вы можете сначала попасть на страницу сведений.

Вы:

а) все равно получить все элементы, потому что вы можете вернуться на страницу списка?

б) просто получить эту информацию для этого одного элемента?

Ни один из ответов не является "правильным", но в конце дня у вас есть три возможных фрагмента информации:

1) идентификатор товара

2) один предмет

3) список товаров (который может содержать или не содержать всю информацию, необходимую для страницы сведений)

Везде, где вы хотите отобразить полную информацию об элементе, он должен иметь доступ к этому элементу через реквизит. Поместить все детали элемента в URL было бы трудно, плюс это сделало бы невозможным выполнение ситуации A.

Так как вы используете redux, имеет смысл получить информацию об элементе из идентификатора в URL.

export default 
  connect((state, props) => ({
    doctor: state.doctorList.find(doctor => 
      doctor.id === props.match.params.id
    )
  }))(DoctorView)

Не кажется ли вам слишком много лишних шагов?

В то время как ответ выше решает проблему отлично, я просто хочу добавить, что используя встроенную функцию с component не рекомендуется отреагировать-маршрутизатор

Вместо того, чтобы делать:

<Route path={`${match.url}/:name`}
  component={ (props) => <DoctorView doctor={this.props.doctors} {...props} />}
  />

Вместо этого вы должны использовать это как:

 <Route path={`${match.url}/:name`}
  render={ (props) => <DoctorView doctor={this.props.doctors} {...props} />}
  />

Это предотвратит создание одного и того же компонента на каждом монтировании, и вместо этого будет использовать один и тот же компонент и соответственно обновлять состояние.

Надеюсь, это поможет кому-то

Другие вопросы по тегам