React/Redux:事件 - 最先进的

Posted

技术标签:

【中文标题】React/Redux:事件 - 最先进的【英文标题】:React/Redux : Events - state of the art 【发布时间】:2019-07-12 17:12:57 【问题描述】:

React 中实现基于事件的模式(发布者/订阅者)的最新技术是什么。

一方面,我们拥有监听这些事件的组件。其中一些组件是可视的,例如绘制其他查询结果的图表可能不是可视的,例如如果我们想要管理查询和结果的组件。

另一方面,任何组件都可以生成事件。

我们的第一个想法是在 Redux 中添加事件及其值的完整列表,并在每个组件上在 shouldComponentUpdate() 中实现一个智能代码,该代码在组件不侦听更改的事件时停止。

这看起来不太优雅,因为所有组件都监听所有事件。有没有更优雅的解决方案(最先进的)?

当然,我们希望能够返回、转发、保存状态和所有这些小细节 :-)

【问题讨论】:

你可以使用上下文来做到这一点。请通过它的docs 这是解决方案的一个很好的部分,但我仍然希望在事件发生变化时通知我的组件。 上下文消费者监听 v=提供给上下文提供者的任何值变化,所以是的,它建立在发布-订阅模式之上 谢谢,我正在阅读.... Redux 非常适合我们作为反应上下文 (***.com/questions/49568073/…) 的替代方案。考虑到这只是更复杂的实际问题的一部分。但仍在寻找更优雅的东西 【参考方案1】:

我认为你需要知道的不是“什么是最先进的”,而是“什么是规范的方式”使用 React 和 Redux 进行发布和订阅。

简短的回答是,如果你有一个足够复杂的应用程序,你应该组织你的商店,以便将应用程序状态划分为slices,并使用container pattern 来分离发布和订阅的责任。这样您就可以避免您提到的问题,即您不知道代码库中的哪些内容正在更改存储以及哪些内容正在响应更改。您可以查看容器组件并了解它如何处理来自其子级的 UI 事件并生成状态更改事件。或者您可以查看容器如何处理状态更改,然后向下钻取层次结构。如果你可以让 Redux 将单个容器的职责分片,那么考虑事件就容易多了。所有其他组件本身并不订阅事件,而是从源自容器组件的道具接收他们需要呈现的更改。并且它们通过 props 向下传递的回调将自己的事件通知容器组件,以便容器可以发布它们。这可能会有很长很长的路要走,如果您觉得需要传递道具太多级别,您可以使用React.children 将嵌套稍微扁平化,或者在极少数情况下使用上下文。

更长的答案有点困难,因为在谈论 React 时发布和订阅并不是特别有意义。 React 最终应该负责渲染。正如您所提到的,并非所有事件都是 UI 事件。但是,如果您对事物进行建模,使得您可以发布和订阅的所有事件都归结为更改商店或对商店更改做出反应,那么您可以构建您的应用程序更多地关注 Redux。管理您正在谈论的查询和结果应该在没有 React 的简单 javascript 模块中完成。然后,您可以使用容器组件将商店粘合到该模块。

人们还使用其他模式,例如动作创建者和选择器。这些很好,因为至少目的是让代码库保持熟悉。但是事情进展得还是有点快,React 朝着 Hooks API 和 React-Redux trying to catch-up 发展。但是切片和容器组件不会去任何地方,它们是分离关注点的自然方式。

【讨论】:

谢谢,我的看法有点偏颇。但我可能没有解释的是,我正在监听的事件是在组件中动态定义的。例如。有一个带有标题字符串字段的属性,它实际上是事件的内容。如何动态地“插入”我的组件与事件(希望很清楚) 我不明白你的意思,但有几点意见:如果你不能应用容器模式,那么你的领域模型或需求一定很复杂。如果您需要创建自定义抽象层来处理这些动态事件,请注意使用类组件和shouldComponentUpdate。阅读 hooks 的动机:reactjs.org/docs/hooks-intro.html#motivation. 假设一个字段的内容,#title,例如组件内的纯 html 文本可能是事件的实际值( $selectedYear )。这将是一个州的“内部”领域。因此,当 $selectedYear 更改时,框会更新,但我也可以直接更改字段#title。希望现在更清楚一点【参考方案2】:

redux 存储事件 重新选择/连接以订阅它们 (https://github.com/reduxjs/reselect#connecting-a-selector-to-the-redux-store)

import  connect  from 'react-redux'
import  toggleTodo  from '../actions'
import TodoList from '../components/TodoList'
import  getVisibleTodos  from '../selectors'

const mapStateToProps = (state) => 
  return 
    todos: getVisibleTodos(state)
  


const mapDispatchToProps = (dispatch) => 
  return 
    onTodoClick: (id) => 
      dispatch(toggleTodo(id))
    
  


const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

export default VisibleTodoList

现在您将订阅的事件作为组件中的道具,仅当道具更改时组件才会重新渲染。不需要 shouldComponentUpdate 因为你的组件不必监听整个 store,它只会获取你在选择器中定义的 store 的一部分。

【讨论】:

以上是关于React/Redux:事件 - 最先进的的主要内容,如果未能解决你的问题,请参考以下文章

在 React、Redux-Form 和 GraphQL 中选择输入中的 onChange 事件从数据库中查询

从 React 中的子组件调用父组件中定义的事件处理程序

React: 研究React Redux的使用

react redux 公共状态管理---数据的渲染,数据的修改,再把修改的数据渲染到当前组件

Jest 测试失败,未定义窗口

React Redux 中的异步 ActionCreator