Как передать набор узлов реакции на несвязанные компоненты - PullRequest
1 голос
/ 26 марта 2020

У меня есть вопрос о React, вот упрощенная версия приложения React.

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

Также в мобильной версии приложения отображается другое меню.

function App() {
    return <Router>
        <PrimaryMenu/>

        <SecondaryMenu/>

        <LayoutContent/>
        {/* This block is rendered only on mobile devices */}
        <Responsive  {...Responsive.onlyMobile}>
            <SecondaryMenu/>
        </Responsive>
    </Router>;
}

LayoutContent будет отображать фактическое содержимое страницы (с использованием компонента Page) в соответствии с правила маршрутизации, и каждый компонент страницы может отображать свое собственное вторичное меню, подобное этому (например, у page1 есть собственное подменю, у page2 есть другое, у page3 нет.)

<Page title='Page 1 - With secondary menu'>
    <SecondaryMenuItems>
        {/* I want this content as children of secondary menu in both mobile and desktop menubars */}
        <li>Page 1 item 1</li>
        <li>Page 1 item 2</li>
    </SecondaryMenuItems>
</Page>

Я пытался реализовать его с помощью контекстов React но если я храню дочерние узлы в контексте, запускается бесконечный рендер. Я изменил его, чтобы использовать свойство id в <SecondaryMenuItems/> компоненте, но подход очень fr agile и также имеет некоторые недостатки.

Вот мой рабочий пример , он работает, но, как я уже сказал довольно красиво agile:

  • Что если я буду использовать дубликат идентификатора для вторичных меню?
  • Что если я забуду клавишу вторичного меню?

Также, если вы переключаетесь на страницу с меню, а затем go на страницу 3 (у которой нет меню), предыдущее меню страницы остается на экране.

Как выполнить sh это с реакцией? Есть ли предлагаемый способ сделать это?

Более простой способ express Мой вопрос: «Как передать набор реагирующих узлов между несвязанными компонентами (например, компонентами-братьями и сестрами)»

Обновление

Я завершил свой рабочий пример с полученными подсказками, теперь, комбинируя useRef с ReactDOM.createPortal, я достиг конечного результата, который теперь есть в примере.

Ответы [ 2 ]

1 голос
/ 29 марта 2020

Это вариант использования для React Portals . Портал позволит вам визуализировать элементы вторичного меню со страницы в контейнер вторичного меню, который существует где-то еще

Все, что вам нужно сделать, это вызвать React.createPortal при рендеринге страницы, передать визуализированный элемент и целевой узел для рендеринга в независимо от положения в дереве DOM

Я отредактировал ваш пример, используя порталы здесь https://codesandbox.io/s/secondary-menu-example-vbm3x. Это, конечно, базовый c пример, для удобства вы можете абстрагировать порталы logi c в отдельный компонент и / или передать ссылку на dom из parent вместо вызова getElementById при монтировании

0 голосов
/ 29 марта 2020

Рендеринг одних и тех же дочерних элементов в нескольких узлах-братьях

Вопрос задает вопрос "как передать набор реагирующих узлов". В идеале нет. Если вы визуализируете узлы где-то в вашей иерархии с намерением использовать их в другом месте , возможно, вы используете неправильную стратегию.

Если вам нужно визуализировать одни и те же компоненты в разных местах, создайте функцию, которая визуализирует компоненты, и вызовите ее из обоих мест. Другими словами, всегда передает информацию, а не отображаемые элементы .

Визуализация внутри маршрутизатора

В типичном одностраничном приложении Маршрутизатор отобразит все компоненты (не статичные c). Вот как пример должен был это сделать. Компонент маршрутизации (LayoutContent) должен был отвечать за непосредственное отображение «пройденных узлов» (SecondaryMenu).

<Route path="/page1">
  <Page title="Page 1 - With secondary menu">
    <SecondaryMenu id="menu1"> {/* <- use SecondaryMenu instead of SecondaryMenuItems */}
      <li>Page 1 item 1</li>
      <li>Page 1 item 2</li>
    </SecondaryMenu>           {/* <- use SecondaryMenu instead of SecondaryMenuItems */}
  </Page>
</Route>

Когда рендеринг внутри маршрутизатора невозможен

Если по какой-то причине компонент маршрутизации не может визуализировать контент напрямую, то решение для одностраничного приложения (или маршрутизации), вероятно, является неправильным решением. Вот. Вопрос не содержит никакой информации о том, почему компоненты не могут быть отображены внутри маршрутизатора, смело редактируйте вопрос и комментируйте с дополнительной информацией.

Другой способ достижения этого примера - это не быть компонентом маршрутизации (т. е. не LayoutContent) и SecondaryMenu проверять путь страницы и условно отображать соответствующий контент на основе этого. Может показаться глупым вручную выполнять условную визуализацию на основе пути, когда есть компонент маршрутизатора, который делает это за вас, и я бы согласился. Решение состоит в том, чтобы вообще не использовать маршрутизатор. Попытка отобразить детей в роутере и передать их имеет сильный запах кода.

В иерархической структуре React, если требуется одна и та же информация, принимайте решения о рендеринге в нескольких местах (в данном случае это путь), переместите эту информацию до ближайшего родителя всех компонентов и передайте ее как подпорки. или как контекст.

Предотвращение столкновений идентификаторов

«Что если я использую дублированный идентификатор для вторичных меню?»

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

function SecondaryMenuItems({ children, idPrefix, path }) {
  if (path == '/path1') {
    return (
      <ul id={`${idPrefix}-newlist`}>

На клавишах

"Что если я забуду дополнительную клавишу меню?"

Реактивные ключи должны быть уникальными только в отображаемом списке . Фактически, ключи - это просто оптимизация, предотвращающая необходимость повторного рендеринга React сгенерированного списка при каждом проходе. Если вы забудете включить ключ (или ошибочно выберете ключ), React будет каждый раз пересматривать список, но это не более серьезно. В простых случаях вы не заметите падения производительности.

...