React-Redux 设计模式:"deep" 组件应该连接到 Redux,还是从 parent 组件接收道具?
React-Redux design pattenrs: Should a "deep" component be wired to Redux, or receive props from parent components?
我正在构建一些在前端使用 React 和 Redux 的即时消息应用程序。我有 "Main"(初始化网络套接字并呈现其他组件)、"Chat"、"FriendsList" 和 "Friend"
等组件
我经常发现自己在想,我是否应该将 child 或 grandchild 直接连接到 Redux(假设它需要它),或者从 parent/grandparent.
例如,我在主组件中渲染 "Chat" 是这样的:
<Chat
onTyping={this.onTyping}
onSubmitMessage={(value) => { this.submitMessage(value) }}
messages={this.props.messages[this.props.activeFriend] || []}//This comes from Redux
isMessagingAvailable={this.isMessagingAvailable()}
/>
如您所见,我传递了一个 "messages" 道具,它又来自 Redux。我当然可以单独将 Chat 连接到 Redux。
那么问题是,在这种情况下是否有关于最佳实践的约定。 每个使用全局状态的组件都应该直接连接到 Redux 吗?
TL;DR;
模块化设计背后的理念是拥有尽可能多的通用组件。
这些组件应该独立于外部世界(即 Redux Store)。
以我的理解,任何应用程序的结构都应该是这样的:
- 您有满足其目的的根级组件。喜欢:
input box
- 然后你有一个复合组件,它将使用这些根组件。就像处理错误标签和输入一样。
- 然后你就形成了高阶组件(HOCs)。这些是业务组件,并且具有正在发生的事情的上下文。这些组件应该可以访问 Redux 存储。
示例:
让我们创建一个包含基本信息的表单:
- 名字
- 姓氏
- 年龄
- 电子邮件
对于这样的表单,您需要以下组件:
- 文本输入组件
- 带有文本 prevention/validation 逻辑的数字输入组件。
您可以将 textInput
用于 FirstName
、lastName
和 email
。所以如果你直接把它绑定到 store,你就是在让它依赖于你自己的 redux 结构。所以这些组件不能在其他任何地方使用。
因此,最好的想法是创建能够接受 props 并执行其任务的哑组件。
您的用例。
您有以下模块:
- 主要
- 聊天
- 好友列表
- 朋友
将来,您打算再添加几个模块:
- 人工智能/机器人聊天
- 群聊
现在个人、机器人和群聊的聊天 window 会很相似,但商店结构会很困难。尤其是群聊。
那么你如何决定哪个组件应该绑定到存储?
您应该为您的视图创建嵌套组件层次结构,并为您的业务模块创建 HOC。这样,您的视图组件不依赖于商店。您的 HOC 将提供数据,仅此而已。
因此,在您的情况下,您将拥有以下 HOC:
- 直接聊天
- 机器人聊天
- 群聊
- 联系人
- 仪表板
您可以拥有以下视图组件:
- 聊天组件:用于所有聊天类型。
- 联系人组件:用于好友列表/联系人视图
- 列表组件:用于浏览器联系人、添加成员视图和管理成员视图。
恕我直言,这真的要视情况而定:
1) 如果 Child 组件独立使用数据,它总是从全局状态树的同一个分支获取数据:我会将它连接到 Redux。
一个总是从state.tasks
获取任务列表的任务列表组件
一个 CurrentUserDetail 组件,它总是从 state.currentUser
获取用户信息
2) 如果子组件根据其父组件使用数据:我会通过道具从父组件获取数据。或者听从父级如何从全局状态中获取数据,然后将其连接到 Redux 并获取相应的数据:
一个 Task 组件,它从其父 TaskList 组件获取每个任务的任务数据
一个TaskList组件,从它的parent获取taskListID,然后获取对应的任务列表。例如:taskListID="Martin" -> state.tasks['Martin']
我正在构建一些在前端使用 React 和 Redux 的即时消息应用程序。我有 "Main"(初始化网络套接字并呈现其他组件)、"Chat"、"FriendsList" 和 "Friend"
等组件我经常发现自己在想,我是否应该将 child 或 grandchild 直接连接到 Redux(假设它需要它),或者从 parent/grandparent.
例如,我在主组件中渲染 "Chat" 是这样的:
<Chat
onTyping={this.onTyping}
onSubmitMessage={(value) => { this.submitMessage(value) }}
messages={this.props.messages[this.props.activeFriend] || []}//This comes from Redux
isMessagingAvailable={this.isMessagingAvailable()}
/>
如您所见,我传递了一个 "messages" 道具,它又来自 Redux。我当然可以单独将 Chat 连接到 Redux。
那么问题是,在这种情况下是否有关于最佳实践的约定。 每个使用全局状态的组件都应该直接连接到 Redux 吗?
TL;DR;
模块化设计背后的理念是拥有尽可能多的通用组件。
这些组件应该独立于外部世界(即 Redux Store)。
以我的理解,任何应用程序的结构都应该是这样的:
- 您有满足其目的的根级组件。喜欢:
input box
- 然后你有一个复合组件,它将使用这些根组件。就像处理错误标签和输入一样。
- 然后你就形成了高阶组件(HOCs)。这些是业务组件,并且具有正在发生的事情的上下文。这些组件应该可以访问 Redux 存储。
示例:
让我们创建一个包含基本信息的表单:
- 名字
- 姓氏
- 年龄
- 电子邮件
对于这样的表单,您需要以下组件:
- 文本输入组件
- 带有文本 prevention/validation 逻辑的数字输入组件。
您可以将 textInput
用于 FirstName
、lastName
和 email
。所以如果你直接把它绑定到 store,你就是在让它依赖于你自己的 redux 结构。所以这些组件不能在其他任何地方使用。
因此,最好的想法是创建能够接受 props 并执行其任务的哑组件。
您的用例。
您有以下模块:
- 主要
- 聊天
- 好友列表
- 朋友
将来,您打算再添加几个模块:
- 人工智能/机器人聊天
- 群聊
现在个人、机器人和群聊的聊天 window 会很相似,但商店结构会很困难。尤其是群聊。
那么你如何决定哪个组件应该绑定到存储?
您应该为您的视图创建嵌套组件层次结构,并为您的业务模块创建 HOC。这样,您的视图组件不依赖于商店。您的 HOC 将提供数据,仅此而已。
因此,在您的情况下,您将拥有以下 HOC:
- 直接聊天
- 机器人聊天
- 群聊
- 联系人
- 仪表板
您可以拥有以下视图组件:
- 聊天组件:用于所有聊天类型。
- 联系人组件:用于好友列表/联系人视图
- 列表组件:用于浏览器联系人、添加成员视图和管理成员视图。
恕我直言,这真的要视情况而定:
1) 如果 Child 组件独立使用数据,它总是从全局状态树的同一个分支获取数据:我会将它连接到 Redux。
一个总是从state.tasks
获取任务列表的任务列表组件
一个 CurrentUserDetail 组件,它总是从 state.currentUser
获取用户信息
2) 如果子组件根据其父组件使用数据:我会通过道具从父组件获取数据。或者听从父级如何从全局状态中获取数据,然后将其连接到 Redux 并获取相应的数据:
一个 Task 组件,它从其父 TaskList 组件获取每个任务的任务数据
一个TaskList组件,从它的parent获取taskListID,然后获取对应的任务列表。例如:taskListID="Martin" -> state.tasks['Martin']