Как изменять state компонента react js извне?

В проекте потребовалось динамически создавать и показывать простое модальное окно по клику на кнопке.
Задумка такая: при клике генерируется событие, все слушатели как-то на него реагируют. Среди них есть компонент модального окна, который на основе получаемых данных рендерит соответствующий блок или, при необходимости, обновляет в нем данные.

Можно было бы взять любой шаблонизатор, тот же nunjucks, который мне как родной, и создавать это самое окно.
Но так как в дальнейшем в проекте скорее всего будут более сложные элементы, я решил с заделом на будущее взять в качестве View React js, с которым , правда, совсем никогда не работал.

Получилось как-то так:
....
        this.on('showModal', function (data) {
            ReactDOM.render(
                <this.renderWindow data={data} />,
                this.el
            );
        });
....

Модальное окно создается, все ок. Теперь его надо как-то скрывать. Добавляю состояние this.state.show.
Теперь по клику оно даже скрывается.
Но по событию 'showModal', оно повторно не показывается. Я так понимаю, что вызывается ReactDOM.render(...); Реакт проверяет состояние - оно не изменилось, this.state.show все еще равно false, и он просто ничего не делает.

Я смотрел примеры реализации модального окна на Реакте. В них всегда кнопка "Показать окно" является частью компонента и просто меняет state.
У меня эта кнопка находится вообще в другом месте, рендерится на сервере и я ее никак не хочу связывать с окном или делать реакт-компонентом. Хотелось бы просто по событию менять state компонента.
Но как это сделать - не пойму.
Или лучше вообще в таком случае не тащить Реакт в проект и сделать view на чем-то другом?
  • Вопрос задан
  • 7095 просмотров
Пригласить эксперта
Ответы на вопрос 3
risentveber
@risentveber
fullstack web developer
Просто подпишетесь на это событие в методе componentDidMount и меняйте state как вам вздумается.
Ответ написан
@Itvanya
Странная проблема.. React - это view, а весь state мы храним, используя Flux-архитектуру (redux, в данном случае). На уровне app пишем редьюсер, который отвечает за активность модального окна. Если окно активно - рендерим его. Повтовюсь, в реакте на уровне всего приложения мы никогда не делаем подобных хаков, которые написаны выше, а вместо весь state храним в redux store. Это, действительно, удобно для независимых операций. А если пытаться сотворить такое на уровне компонентов, то проще не использовать реакт.
Ответ написан
Комментировать
@Faliah
Сначала мне показалось, что это извращение - использовать Реакт, вместо шаблонизатора, как из пушки по воробьям.
Но, в самом использовании по-моему нет ничего особенного - вот тут собрал вам демку

Вкратце:
  • Реакт не будет остлеживать состояние глобальных переменных и перерисовывать компонент при их изменении
  • Вместо этого вам нужно воспользоваться lifecycle хуками и, как предлагал коллега выше, внутри этого метода пробросить нужные методы для управления состоянием компонента наружу, хоть в тот же widnow
  • Это позволит вам импользовать одни и те же методы как в дочерних компонентах: обработка клика по оверлею или по кнопке в модальном окне, так и во внешних, по отношению к контексту Реакта, DOM элементах, или, возможно, в каких-то еще бибилиотеках, JQuery и прочих


Если использовать мой компонент, то нужно немного изменить ваш код:
...
  this.on('showModal', function (data) {
    if (!window.modalAttached) {
      ReactDOM.render(
        <ModalWindow data={data} />,
        this.el
      )
    }      
    window.toggleModal();
  }
...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы