Как сообщать изменения состояния пользовательского интерфейса между компонентами React с помощью Redux?

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

В настоящее время я пишу небольшое блог-приложение, в котором вы можете просто создавать и редактировать сообщения. У меня есть диалог для создания сообщения, примерно render метод компонента App возвращает что-то вроде этого:

<div>
    <AppBar ... />
    <PostFormDialog
      addPost={actions.addPost}
      ref="postFormDialog" />
    <PostList
      posts={posts}
      actions={actions} />
</div>

Мой вопрос: должно ли состояние диалога (открытого или закрытого) быть частью объекта состояния компонента App? И поэтому открытие и закрытие диалога запускается через действие вместо того, чтобы делать что-то вроде следующего:

onTriggerCreatePostDialog(e) {
    this.refs.postFormDialog.show();
}

где onTriggerCreatePostDialog запускается через какой-либо прослушиватель кликов на кнопке "Создать" или около того.

Мне кажется немного странным, что я делаю это через действия, потому что вводит вид "косвенности".

Однако, предполагая, что я хочу повторно использовать диалог для действия редактирования, я должен иметь возможность открыть диалог из элементов, которые глубже в структуре компонента, например, из компонента Post, который является дочерним элементом PostList. Я мог бы сделать функцию onTriggerCreatePostDialog вниз по иерархии с помощью свойства props, но это кажется мне громоздким...

Таким образом, int end также связан с сообщением между компонентами, которые не находятся в прямой зависимости между родителями и дочерними элементами. Есть ли другие варианты? Должен ли я каким-то образом использовать глобальную шину событий? В настоящее время я не уверен.

Ответы

Ответ 1

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

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

Наше состояние сокращения состоит в основном из данных, собранных через запросы xhr или из общего состояния. Примером общего состояния будет управление временным диапазоном между несколькими компонентами, которые используют этот диапазон для отображения данных. В этом случае мы будем инициировать действие сокращения; обновить состояние даты с тем, на что оно было изменено (в то же время обновляя некоторые другие элементы состояния через xhr), а затем, в конечном счете, вернется к компонентам и повторно отобразит их.

С учетом сказанного, запуск действий с помощью refs является полностью приемлемым, это примерно то, что конкретный вариант использования.

Чтобы ответить на второй вопрос; redux рекомендует использовать концепцию Smart and Dumb. Таким образом, вы правы, что передаете функцию вниз по дереву для использования немых компонентов.

Мы используем mapDispatchToProps в нашей connect настройке. Поэтому в основном вы передаете функцию, которая возвращает объект функции "диспетчеры". Вы сможете получить доступ к этим функциям непосредственно в своем интеллектуальном компоненте this.props.

Пример mapDispatchToProps

function mapDispatchToProps(dispatch) {
  return {
    myAction: () => dispatch(actions.myAction()),
  };
}

Итак, это работает в 99% случаев, но я столкнулся с некоторыми угловыми случаями, когда мы используем глобальную шину событий, поэтому не бойтесь использовать их, пытаясь придерживаться метода Smart/Dumb component насколько это возможно.

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

Ответ 2

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

App.render() должно быть примерно так:

render() {
  const { showDialog } = this.props;

  return (
    <div>
      <AppBar ... />
      { showDialog ? <PostFormDialog ... /> : false }
      <PostList ... />
    </div>
  );
}

где mapStateToProps будет чем-то вроде state => {{ showDialog: state.showDialog }}

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