Redux体系结构。 是或否?

该材料的作者(我们今天出版的翻译版)说,他是Hike Messenger团队的成员,该团队致力于该应用程序的新功能。 该团队的目标是将现实转化为现实,并探索用户可能喜欢的想法。 这意味着开发人员需要迅速采取行动,并且他们经常必须对他们正在研究的创新进行更改,以使用户的工作尽可能方便和愉快。 他们更喜欢使用React Native进行实验,因为该库可以加快开发速度,并允许您在不同平台上使用相同的代码。 另外,他们使用Redux库。



当Hike的开发人员开始研究新事物时,然后在讨论所研究的解决方案的体系结构时,他们会遇到以下几个问题:

  • 正如他们所说,这是一个实验性的机会,它“不会飞起来”,因此必须放弃。 鉴于此,是否有必要花时间设计应用程序体系结构?
  • 实验性应用程序只是MVP,这是一种最低可行的产品,具有1-2个屏幕,需要尽快创建。 鉴于此,我应该联系Redux吗?
  • 您如何证明产品经理为实验应用程序准备支持基础结构所花费的时间?

实际上,Redux可以帮助您找到所有这些问题的正确答案。 Redux架构有助于将应用程序状态与React分开。 它允许您创建位于应用程序顶层的全局存储库,并为所有其他组件提供状态访问。

责任分工


什么是“职责分离”? 维基百科就是这样说的:“在计算机科学中,职责划分是将计算机程序划分为功能块的过程,这些功能块之间的功能应尽可能少地重叠。 在更一般的情况下,职责划分是通过将问题分解为交互的过程来解决子任务,从而简化了解决问题的单个过程。

Redux的体系结构允许您在应用程序中实施职责分离的原理,将其分为四个块,如下图所示。


Redux架构

这是这些块的简要说明:

  • 表示形式或用户界面组件(UI组件)类似于纯功能(即那些不会更改传输给它们的数据并具有其他一些属性的功能),它们负责根据从商店传输到屏幕上的数据在屏幕上显示信息。 它们不会直接更改数据。 当事件发生时,或者如果用户与他们进行交互,他们将转向操作的创建者。
  • 动作创建者负责创建和分发动作。
  • Reducer接收计划的操作并更新存储库的状态。
  • 数据存储区负责存储应用程序数据。

以Redux的架构为例。

如果不同的组件需要相同的数据怎么办?


远足应用程序有一个屏幕,显示用户的朋友列表。 有关其数量的信息显示在此屏幕的顶部。


远足应用中的“朋友”屏幕

这里有3个React组件:

  • FriendRow是一个组件,其中包含用户的朋友名称和有关他的一些其他信息。
  • FriendsHeader一个显示题词“ MY FRIENDS”和有关朋友数量信息的组件。
  • ContainerView是一个容器组件,它将由FriendsHeader组件表示的屏幕标题和通过遍历包含有关用户朋友的信息的数组而获得的朋友列表组合在一起,该数组的每个元素都由FriendRow组件显示在屏幕上。

这是friendsContainer.js的代码,用于说明上述内容:

 class Container extends React.Component {   constructor(props) {     super(props);     this.state = {       friends: []     };   }   componentDidMount() {     FriendsService.fetchFriends().then((data) => {       this.setState({         friends: data       });     });   }   render() {     const { friends } = this.state;     return (       <View style={styles.flex}>       <FriendsHeader count={friends.length} text='My friends' />       {friends.map((friend) => (<FriendRow {...friend} />)) }       </View>     );   } } 

创建此类应用程序页面的绝对显而易见的方法是将有关好友的数据加载到容器组件中,并将其作为属性传递给子组件。

让我们考虑一下以下事实:在应用程序中使用的其他一些组件中可能需要有关朋友的数据。


远足聊天屏幕

假设该应用程序有一个聊天屏幕,其中还包含一个朋友列表。 可以看出,与好友列表一起使用的屏幕和聊天屏幕上使用了相同的数据。 在类似情况下该怎么办? 我们有两个选择:

  • 您可以在负责显示聊天列表的ComposeChat组件中再次下载朋友数据。 但是,这种方法并不是特别好,因为它的使用将意味着重复数据,并可能导致同步问题。
  • 您可以在顶级组件(应用程序的主容器)中下载有关朋友的数据,并将此数据传输到负责显示朋友列表和聊天列表的组件。 另外,我们需要将函数传递给这些组件以更新好友数据,这对于支持组件之间的数据同步是必需的。 这种方法将导致这样一个事实,即顶层组件实际上会被打包有不直接使用的方法和数据。

这两种选择都不那么吸引人。 现在让我们看看如何使用Redux架构解决我们的问题。

使用Redux


在这里,我们讨论的是使用存储,动作创建者,缩减器和用户界面的两个组件来组织数据工作。

▍1。 数据仓库


存储库包含有关用户朋友的上载数据。 如果需要,可以将该数据发送到任何组件。

▍2。 动作创作者


在这种情况下,操作的创建者用于调度旨在保存和更新有关朋友的数据的事件。 这是friendsActions.js的代码:

 export const onFriendsFetch = (friendsData) => { return {   type: 'FRIENDS_FETCHED',   payload: friendsData }; }; 

▍3。 减速器


减速器等待代表计划的动作的事件到达并更新其朋友。 这是friendsReducer.js的代码:

 const INITIAL_STATE = {      friends: [],   friendsFetched: false }; function(state = INITIAL_STATE, action) {   switch(action.type) {   case 'FRIENDS_FETCHED':       return {           ...state,           friends: action.payload,           friendsFetched: true       };   } } 

▍4。 朋友列表组件


该容器组件可查看好友数据并在其更改时更新界面。 此外,如果没有数据,他负责从存储库下载数据。 这是friendsContainer.js的代码:

 class Container extends React.Component {   constructor(props) {     super(props);   }   componentDidMount() {     if(!this.props.friendsFetched) {       FriendsService.fetchFriends().then((data) => {         this.props.onFriendsFetch(data);       });     }   }   render() {     const { friends } = this.props;     return (       <View style={styles.flex}>       <FriendsHeader count={friends.length} text='My friends' />       {friends.map((friend) => (<FriendRow {...friend} />)) }       </View>     );   } } const mapStateToProps = (state) => ({ ...state.friendsReducer }); const mapActionToProps = (dispatch) => ({ onFriendsFetch: (data) => {   dispatch(FriendActions.onFriendsFetch(data)); } }); export default connect(mapStateToProps, mapActionToProps)(Container); 

5英镑 聊天清单组件


该容器组件还使用来自存储的数据并响应其更新。

关于Redux架构实施


使上面描述的体系结构进入工作状态可能需要一两天,但是当需要对项目进行更改时,可以非常简单,快速地进行更改。 如果需要在使用有关好友数据的应用程序中添加新组件,则可以执行此操作而不必担心数据同步,也不必重做其他组件。 删除组件也是如此。

测试中


使用Redux时,可以独立测试每个应用程序块。
例如,每个用户界面组件都可以独立于数据而轻松进行单元测试。 关键是表示此类组件的函数始终针对相同数据返回相同的表示。 这使应用程序可预测,并减少了在数据可视化期间发生错误的可能性。

每个组件都可以使用各种数据进行全面测试。 这样的测试揭示了隐藏的问题,并有助于确保高质量的代码。

应该注意的是,不仅负责数据可视化的组件,而且减速器和动作创建者都可以进行独立测试。

Redux很棒,但是使用这项技术会遇到一些困难。

使用Redux的困难


template多余的模板代码


为了在应用程序中实现Redux架构,您必须花费大量时间,同时遇到各种奇怪的概念和实体。

这些是所谓的雪橇(thunk),reduces(reducer),actions(action),中间件层(middlewares),它们是mapStateToPropsmapDispatchToProps功能。 学习所有这些都需要花费时间,并且为了学习如何正确使用它,需要实践。 项目中有很多文件,例如,为了使数据可视化,组件中的一个小更改可能需要对四个文件进行更改。

Red Redux保管库为单例


在Redux中,尽管组件可以具有多个实例,但是数据仓库是使用单例模式构建的。 通常,这不是问题,但是在某些情况下,这种数据存储方法会带来一些困难。 例如,假设有一个组件的两个实例。 当这些实例中的任何一个发生数据更改时,这些更改都会影响另一个实例。 在某些情况下,这种行为可能是不希望的;组件的每个实例可能都必须使用其自己的数据副本。

总结


回想一下我们的主要问题,那就是实现Redux架构是否值得花费时间和精力。 在回答这个问题时,我们对Redux说“是”。 这种体系结构有助于节省开发和开发应用程序的时间和精力。 使用Redux可使程序员更轻松地对应用程序进行频繁更改,并使测试更加容易。 当然,Redux架构提供了大量的样板代码,但它有助于将代码分解为便于使用的模块。 每个这样的模块都可以独立于其他模块进行测试,这有助于在开发阶段识别错误并确保高质量的程序。

亲爱的读者们! 您是否在项目中使用Redux?

Source: https://habr.com/ru/post/zh-CN426473/


All Articles