Как сообщать изменения состояния пользовательского интерфейса между компонентами 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 }}
Что касается доставки создателя действия, то передача его дерева реквизита, вероятно, является правильным способом, если у вас нет хорошего места, где имеет смысл иметь еще один интеллектуальный компонент.