Я только начал работать с ReactJS и немного застрял на проблеме, которая у меня есть.
Мое приложение, по сути, представляет собой список с фильтрами и кнопкой для изменения макета. На данный момент я использую три компонента: <list />
, < Filters />
и <TopBar />
, теперь , очевидно , когда я изменить настройки < Filters />
я хочу , чтобы вызвать какой - либо метод в <list />
обновить мой взгляд.
Как я могу заставить эти 3 компонента взаимодействовать друг с другом или мне нужна какая-то глобальная модель данных, в которую я могу просто внести изменения?
javascript
reactjs
woutr_be
источник
источник
Ответы:
Лучший подход будет зависеть от того, как вы планируете расположить эти компоненты. Несколько примеров сценариев, которые приходят на ум прямо сейчас:
<Filters />
является дочерним компонентом<List />
<Filters />
и<List />
являются потомками родительского компонента<Filters />
и<List />
жить в отдельных корневых компонентах полностью.Могут быть и другие сценарии, о которых я не думаю. Если ваш не вписывается в эти, то дайте мне знать. Вот несколько очень грубых примеров того, как я справлялся с первыми двумя сценариями:
Сценарий № 1
Вы можете передать обработчик из
<List />
в<Filters />
, который затем может быть вызван дляonChange
события, чтобы отфильтровать список с текущим значением.JSFiddle для # 1 →
Сценарий № 2
Аналогично сценарию № 1, но родительский компонент будет тем
<Filters />
, который передаст функцию-обработчик , и передаст отфильтрованный список<List />
. Мне нравится этот метод лучше, так как он отделяет<List />
от<Filters />
.JSFiddle для # 2 →
Сценарий № 3
Когда компоненты не могут обмениваться данными между родителями и потомками, в документации рекомендуется настроить глобальную систему событий .
источник
updateFilter
в<Filters />
и массив какitems
в<List />
. Вы можете использовать эти дочерние компоненты у других родителей с другим поведением, вместе или в одиночку. Например, если вы хотите отобразить динамический список, но не нуждаетесь в фильтрации.Существует несколько способов взаимодействия компонентов. Некоторые из них могут подойти для вашего использования. Вот список некоторых, которые я нашел полезным знать.
реагировать
Прямое общение родителей и детей
Здесь дочерний компонент будет вызывать обратный вызов, предоставленный родителем со значением, и родитель сможет получить значение, предоставленное дочерними элементами в родительском элементе.
Если вы создаете функцию / страницу своего приложения, лучше иметь одного родителя, управляющего обратными вызовами / состоянием (также называемого
container
илиsmart component
), и все дочерние элементы должны быть без состояний, только сообщая обо всем родителю. Таким образом, вы можете легко «поделиться» состоянием родителя с любым ребенком, которому это нужно.контекст
React Context позволяет хранить состояние в корне иерархии компонентов и иметь возможность легко внедрять это состояние в очень глубоко вложенные компоненты без необходимости передавать реквизиты каждому промежуточному компоненту.
До сих пор контекст был экспериментальной функцией, но в React 16.3 доступен новый API.
Потребитель использует шаблон функции render prop / children
Проверьте этот блог для более подробной информации.
Перед React 16.3 я бы рекомендовал использовать реакцию-трансляцию, которая предлагает довольно похожий API, и использовать прежний контекстный API.
Порталы
Используйте портал, когда вы хотите, чтобы два компонента были расположены близко друг к другу, чтобы заставить их взаимодействовать с простыми функциями, как в обычном родительском / дочернем элементе, но вы не хотите, чтобы эти два компонента имели отношения родительский / дочерний в DOM, потому что из видимых / CSS ограничений, которые это подразумевает (например, z-index, opacity ...).
В этом случае вы можете использовать «портал». Существуют разные библиотеки реагирования, использующие порталы , обычно используемые для модальных окон, всплывающих окон, всплывающих подсказок ...
Учтите следующее:
Может создать следующий DOM при визуализации внутри
reactAppContainer
:Подробнее здесь
игровые автоматы
Вы определяете слот где-то, а затем заполняете слот из другого места вашего дерева визуализации
Это немного похоже на порталы, за исключением того, что заполненное содержимое будет отображаться в определенном вами слоте, в то время как порталы обычно визуализируют новый узел dom (часто дочерний элемент document.body)
Проверьте библиотеку response-slot-fill
Шина событий
Как указано в документации React :
Есть много вещей, которые вы можете использовать для настройки шины событий. Вы можете просто создать массив слушателей, и при публикации события все слушатели получат событие. Или вы можете использовать что - то вроде EventEmitter или PostalJs
Flux
Flux - это, по сути, шина событий, за исключением того, что получатели событий являются магазинами. Это похоже на базовую систему шины событий, за исключением того, что состояние управляется вне React
Оригинальная реализация Flux выглядит как попытка хакерской работы с источником событий.
Redux для меня - это реализация Flux, наиболее близкая к источникам событий, которая обладает многими преимуществами источников событий, такими как возможность путешествовать во времени. Он не связан строго с React и может также использоваться с другими библиотеками функциональных представлений.
Видео-учебник Egghead Redux действительно хорош и объясняет, как он работает внутри (это действительно просто).
курсоры
Курсоры взяты из ClojureScript / Om и широко используются в проектах React. Они позволяют управлять состоянием вне React, и позволяют нескольким компонентам иметь доступ на чтение / запись к одной и той же части состояния без необходимости что-либо знать о дереве компонентов.
Существует множество реализаций, в том числе ImmutableJS , React-курсоры и Omniscient
Edit 2016 : кажется, что люди соглашаются, что курсоры работают хорошо для небольших приложений, но это плохо масштабируется в сложных приложениях. Om Next больше не имеет курсоров (хотя Om изначально ввел эту концепцию)
Архитектура вяза
Архитектура вяза - это архитектура, предложенная для языка вяза . Даже если Elm не ReactJS, архитектура Elm также может быть реализована в React.
Дэн Абрамов, автор Redux, реализовал архитектуру Elm с использованием React.
И Redux, и Elm действительно великолепны и имеют тенденцию расширять возможности поиска событий на внешнем интерфейсе, позволяя отлаживать путешествия во времени, отменять / возвращать, воспроизводить ...
Основное различие между Redux и Elm состоит в том, что Elm, как правило, более строг в управлении государством. В Elm вы не можете иметь локальное состояние компонента или перехватывать / демонтировать хуки, и все изменения DOM должны быть вызваны глобальными изменениями состояния. Архитектура Elm предлагает масштабируемый подход, который позволяет обрабатывать ВСЕ состояние внутри одного неизменного объекта, в то время как Redux предлагает подход, который предлагает вам обрабатывать МОСТ состояния в одном неизменном объекте.
Несмотря на то, что концептуальная модель Elm очень элегантна, а архитектура позволяет хорошо масштабироваться для больших приложений, на практике это может быть затруднено или потребовать дополнительных шаблонов для решения простых задач, таких как выделение фокуса для ввода после его монтирования или интеграция с существующей библиотекой. с императивным интерфейсом (например, плагин JQuery). Связанная проблема .
Кроме того, архитектура Elm включает в себя больше кода кода. Это не настолько многословно или сложно писать, но я думаю, что архитектура Elm больше подходит для языков со статической типизацией.
FRP
Такие библиотеки, как RxJS, BaconJS или Kefir, могут использоваться для создания потоков FRP для обработки связи между компонентами.
Вы можете попробовать, например, Rx-React
Я думаю, что использование этих библиотек очень похоже на использование языка ELM с сигналами .
Платформа CycleJS не использует ReactJS, но использует vdom . Он имеет много общего с архитектурой Elm (но его проще использовать в реальной жизни, поскольку он позволяет использовать VDOM-хуки), и он широко использует RxJ вместо функций и может стать хорошим источником вдохновения, если вы хотите использовать FRP с React. CycleJs Egghead видео приятно понять, как это работает.
СНТ
CSP (передача последовательных процессов) в настоящее время популярны (в основном из-за Go / goroutines и core.async / ClojureScript), но вы можете использовать их также в javascript с JS-CSP .
Джеймс Лонг снял видео, объясняющее, как его можно использовать с React.
Саги
Сага - это бэкэнд-концепция из мира DDD / EventSourcing / CQRS, также называемая «диспетчер процессов». Он популяризируется проектом redux-saga , в основном в качестве замены для redux-thunk для обработки побочных эффектов (например, вызовов API и т. Д.). Большинство людей в настоящее время думают, что это только услуги для побочных эффектов, но на самом деле это больше касается разъединения компонентов.
Это скорее комплимент для архитектуры Flux (или Redux), чем для совершенно новой системы связи, потому что сага в конце выдает действия Flux. Идея состоит в том, что если у вас есть widget1 и widget2, и вы хотите, чтобы они были развязаны, вы не можете запустить действие таргетинга widget2 из widget1. Таким образом, вы делаете widget1 только действия, которые нацелены на себя, и сага является «фоновым процессом», который прослушивает действия widget1 и может отправлять действия, которые нацелены на widget2. Сага - это точка соединения между двумя виджетами, но виджеты остаются разъединенными.
Если вам интересно, посмотрите мой ответ здесь
Вывод
Если вы хотите увидеть пример того же маленького приложения, использующего эти разные стили, проверьте ветки этого хранилища .
Я не знаю, какой вариант лучше в долгосрочной перспективе, но мне действительно нравится, как Flux выглядит как источник событий.
Если вы не знакомы с концепциями источников событий, взгляните на этот очень педагогический блог: выверните базу данных с помощью Apache Samza , это необходимо прочитать, чтобы понять, почему Flux хорош (но это может относиться и к FRP). )
Я думаю, что сообщество соглашается с тем, что наиболее многообещающей реализацией Flux является Redux , которая будет постепенно обеспечивать очень продуктивный опыт разработчиков благодаря горячей перезагрузке. Впечатляющее живое кодирование аля видео « Изобретая по принципу» Брета Виктора, возможно!
источник
Хорошо, есть несколько способов сделать это, но я исключительно хочу сосредоточиться на использовании магазина с использованием Redux, который делает вашу жизнь намного проще в этих ситуациях, а не дает вам быстрое решение только для этого случая, использование чистого React приведет к путанице в действительно большое приложение и общение между Компонентами становится все сложнее и сложнее с ростом приложения ...
Так что Redux делает для вас?
Redux - это как локальное хранилище в вашем приложении, которое можно использовать всякий раз, когда вам нужно, чтобы данные использовались в разных местах вашего приложения ...
По сути, идея Redux изначально пришла из потока, но с некоторыми фундаментальными изменениями, включая концепцию наличия единого источника правды путем создания только одного магазина ...
Посмотрите на график ниже, чтобы увидеть некоторые различия между Flux и Redux ...
Рассмотрите возможность применения Redux в вашем приложении с самого начала, если ваше приложение нуждается в связи между компонентами ...
Также для начала полезно прочитать эти слова из документации Redux:
источник
datepicker
(в качестве компонента), и этот компонент может быть загружен из нескольких компонентов, находящихся на одной странице, то какdatepicker
компонент узнает, какое действие следует отправить в редукцию? В этом суть проблемы, связывая действие в одном компоненте с другим, а НЕ с любым другим компонентом . (принять во внимание, чтоdatepicker
сам по себе является глубоким, глубоким компонентом внутри самого модального компонента)redux
и что вы можете хранить, но КАК пройти действие глубоко вниз к тому , что нужно , чтобы вызвать его. Как глубоко компонент знает , что ТОЧНО должен быть вызван? поскольку в примере я дал общий компонент, который должен запускаться для конкретного редуктора, в зависимости от сценария, поэтому он может быть другим редуктором, поскольку модальный модуль выбора даты можно использовать для любого компонента.Это способ, которым я справился с этим.
Допустим, у вас есть <select> для месяца и <select> для дня . Количество дней зависит от выбранного месяца.
Оба списка принадлежат третьему объекту, левой панели. Оба <select> также являются потомками leftPanel <div>
Это игра с обратными вызовами и обработчиками в компоненте LeftPanel .
Чтобы проверить это, просто скопируйте код в два отдельных файла и запустите index.html . Затем выберите месяц и посмотрите, как меняется количество дней.
dates.js
И HTML для запуска левой панели компонента index.html
источник
Я видел, что на этот вопрос уже дан ответ, но если вы хотите узнать больше подробностей, существует всего 3 случая связи между компонентами :
источник
Расширяя ответ @MichaelLaCroix, когда сценарий состоит в том, что компоненты не могут взаимодействовать между какими-либо отношениями родитель-потомок, в документации рекомендуется настроить глобальную систему событий.
В случае
<Filters />
и<TopBar />
не имеет какого - либо из вышеперечисленных отношений, простой глобальный эмиттер может быть использован , как это:componentDidMount
- Подписаться на событиеcomponentWillUnmount
- Отписаться от событияКод React.js и EventSystem
EventSystem.js
NotificationComponent.js
источник
Есть такая возможность, даже если они не являются отношениями Родитель - Ребенок - и это Flux. Для этого есть довольно хорошая (лично для меня) реализация, которая называется Alt.JS (с Alt-Container).
Например, у вас может быть боковая панель, которая зависит от того, что установлено в компоненте Details. Боковая панель компонента связана с SidebarActions и SidebarStore, а Details - это DetailsActions и DetailsStore.
Тогда вы можете использовать AltContainer
Который будет хранить магазины (ну, я мог бы использовать «магазин» вместо «магазины» проп). Теперь {this.props.content} МОЖЕТ БЫТЬ Подробности в зависимости от маршрута. Допустим, что / Details перенаправляет нас к этому представлению. Детали будут иметь, например, флажок, который изменит элемент боковой панели с X на Y, если он будет отмечен.
Технически между ними нет никаких отношений, и было бы трудно обойтись без изменений. Но с этим это довольно легко.
Теперь давайте перейдем к DetailsActions. Мы создадим там
и DetailsStore
И теперь это место, где начинается магия.
Как вы можете видеть, для SidebarActions имеется bindListener.ComponentStatusChanged, который будет использоваться, если будет использоваться setSiteComponent.
сейчас в SidebarActions
У нас есть такая вещь. Он отправит этот объект по вызову. И он будет вызываться, если будет использоваться setSiteComponent в хранилище (которое вы можете использовать в компоненте, например, во время onChange для Button или любого другого)
Теперь в SidebarStore у нас будет
Теперь здесь видно, что он будет ждать DetailsStore. Что это означает? более или менее это означает, что этот метод должен ждать обновления DetailsStore, прежде чем он сможет обновиться сам.
tl; dr One Store прослушивает методы в хранилище и инициирует действие из действия компонента, которое обновит свое собственное хранилище.
Я надеюсь, что это может помочь вам как-то.
источник
Если вы хотите изучить варианты взаимодействия между компонентами и почувствовать, что все сложнее и сложнее, то вы можете рассмотреть возможность использования хорошего шаблона проектирования: Flux .
Это просто набор правил, которые определяют, как вы храните и изменяете состояние приложения и используете его для визуализации компонентов.
Существует множество реализаций Flux, и официальная реализация Facebook является одной из них. Хотя это считается тот, который содержит большую часть стандартного кода, но это легче понять, так как большинство вещей явно.
Некоторые из других альтернатив смущать fluxxor плавкие и перевождите .
источник
Я когда-то был там, где ты сейчас, как новичок, ты иногда чувствуешь неуместно, как реагируют на это. Я попытаюсь решить то же самое, что и сейчас.
Штаты являются краеугольным камнем общения
Обычно все сводится к тому, как вы изменяете состояния в этом компоненте, в вашем случае вы указываете на три компонента.
<List />
: Который, вероятно, будет отображать список элементов в зависимости от фильтра<Filters />
: параметры фильтра, которые изменят ваши данные.<TopBar />
: Список опций.Для организации всего этого взаимодействия вам понадобится более высокий компонент, назовем его App, который будет передавать действия и данные каждому из этих компонентов, так что, например, может выглядеть так
Поэтому, когда
setFilter
вызывается, это повлияет на FilterItem и повторно отрендерить оба компонента; В случае, если это не совсем понятно, я привел вам пример с флажком, который вы можете проверить в одном файле:источник
Следующий код помогает мне установить связь между двумя братьями и сестрами. Настройка выполняется в родительском объекте во время вызовов render () и componentDidMount (). Он основан на https://reactjs.org/docs/refs-and-the-dom.html Надеюсь, что это поможет.
источник
Странно, никто не упомянул
mobx
. Идея похожа наredux
. Если у меня есть часть данных, на которую подписано несколько компонентов, я могу использовать эти данные для управления несколькими компонентами.источник