Как управлять состоянием для многих взаимосвязанных дочерних компонентов в React - PullRequest
0 голосов
/ 04 ноября 2019

Извиняюсь за многословный вопрос, но я не могу придумать простой способ задать это!

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

Мой пользовательский интерфейс в основном SVG, и у меня есть много компонентов, которыеЯ хотел бы функционировать как "огни". Для простоты мы могли бы думать о каждом источнике света как о элементе SVG circle, имеющем непрозрачность 1, когда источник света включен, и непрозрачность 0, когда источник света выключен (и значения между ними иногда тоже бывают). Большинство источников света должны включаться, когда курсор над ними наводится (а затем исчезать после того, как курсор исчезнет). Затем в другой раз пользователь сделает что-то, что вызовет сложную серию поведений для многих источников света. Например, я мог бы хотеть, чтобы определенные типы огней медленно пульсировали, исчезая в унисон. Или я мог бы захотеть, чтобы кольцо огней быстро мигало один раз в последовательности.

Для такого поведения с несколькими источниками света мне потребуется некоторый контроль над огнями на верхнем уровне моего приложения. Но десятки этих источников света очень глубоко вложены в приложение в разных ветвях дерева DOM. Некоторые источники света даже создаются и уничтожаются на основе результатов рендеринга компонентов выше по дереву. Это глубокое вложение и динамическое создание мешают мне вообразить сохранение состояния всех источников света на верхнем уровне приложения.

Вот как я представляю себе реализацию этого (но я не могу соединитьсявсе точки).

  1. Источники света будут отображаться в зависимости от того, где я размещаю их в других компонентах.
  2. Каждый источник света будет классом и будет управлять своим собственным состоянием включения / выключения. Внутри класса он также будет иметь такие функции, как turnOn(), turnOff(), startPulsing(), flashOnce() и другие - но он сам не будет вызывать эти функции.
  3. своего рода единственное число "Контроллер освещения "будет существовать на верхнем уровне приложения и передавать функции register(...), unregister(...) и dispatch(...) через контекст.
  4. Когда каждый источник света монтируется, он" регистрируется "в контроллере, в свою очередь сообщая контроллеру, к каким классам источников света он принадлежит, и он передает ссылку на себя. Контроллер будет хранить массив активных источников света вместе с этой ссылкой и этими классами для каждого источника света. Каждый источник света также «отменяет регистрацию» перед размонтированием.
  5. Любой компонент в приложении может вызывать метод dispatch(...) из контроллера освещения, фактически говоря что-то вроде «включить все источники света, соответствующие outerкласс". Затем контроллер отфильтровывает свой массив источников света в соответствии с классом и вызывает для каждого функцию turnOn().

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

В целом мой подход здесь, похоже, не совсем соответствует рекомендациям React. Я думаю «императивными» терминами, в то время как React работает «декларативными» способами. Так что, возможно, я все делаю неправильно! Я хотел бы получить совет о том, как все это настроить. Я открыт для использования Redux, MobX или других, если вы думаете, что это даст существенные преимущества. Спасибо за чтение!

...