Skip to main content

React Redux

Flux

Flux是一种由Facebook提出的架构,主要解决一些复杂的问题,针对数据的处理、视图之间的交互而衍生出来的思想。

Flux思想规定了状态如何管理,是在框架出现之前的产物。其在状态管理上有一套标准化,框架也希望有一套标准的状态管理解决方案。

Flux

视图触发一个事件会调用dispatch,dispatch会调用action,即不同的动作,action会通过携带的type进入reducer处理函数中的不同逻辑,在相应的逻辑中更改对应的state,当state变化后,会触发视图重新渲染。这样的一整套流程形成了一个回路,这就是Flux思想。

目前许多状态管理器都使用到了Flux思想,如VuexPiniaReduxMobx等。

Redux

Redux并不是解决了公共状态管理的问题,它只是Flux思想的一种解决(实现)方案。

React只是在实现公共状态管理的过程中使用了Redux的解决方案,并衍生出了react-redux,因此Redux本质上与React没有任何关系。在Redux中,数据操作原则是返回一个新的state引用,以此来变更state

Redux生态中,action主要有两种方式:对象式和函数式。

对象式即普通的对象:

export function listAction(newList) {
return {
type: 'GETLIST',
payload: newList
}
}

而函数式action主要是为了解决异步操作的问题,需要使用到redux-thunkredux-promise中间件:

// redux-thunk
export function listAction(page) {
return (dispatch) => {
http('/getList').then((res) => {
dispatch({
type: 'GETLIST',
payload: res.data
})
})
}
}

// redux-promise
export function listAction(page) {
return http('/getList').then((res) => {
return {
type: 'GETLIST',
payload: res.data
}
})
}

Data Flow

数据流向一般是单向数据流,从父流向子,而子是不能直接流向父的。组件是有层级关系的,从上往下形成了一条链条,称为组件树。

在前端开发中,数据一般是state / data,它们都是跟视图直接挂钩的状态。React中最早使用state描述数据和视图的关系,而Vue则使用data更加直接的描述。如果跟视图无关的数据,一般无需使用状态,无需使用数据流,可通过变量声明的方式来描述。

如果子组件需要父组件的数据,通常情况下通过单向数据流一层一层的往下传递,这样做会使得数据的来源很明确。因为在项目开发中,数据的来源非常的重要,这直接影响到了组价如何维护,组件如果出现了数据的异常,可以非常容易得找出其根源。

但是这种方式也有弊端,当组件调用的时候必须注入数据。对于跨级组件来说,需要借助中间层级组件充当媒介来传递数据,会使得中间层级组件数据冗余,多出了许多并不需要使用的数据。

数据流为什么不是双向的?

数据流如果是双向的会带来许多问题,比如数据来源不明确、数据的安全性。

想象这么一个场景,有个父组件(F),它有两个子组件(A、B),F传递数据a给A和B组件。在某个时刻,B将a修改了,此时A中的a突然变化了,当A去F溯源时,F并不知道是哪个子组件(F可能存在多个子组件)修改了a,对于A来说,其数据来源并不明确,也不知道数据时如何被更改的,产生了一定的安全性问题。

Context

在单向数据流机制下,如果组件想跨级传递数据,只能通过一层一层的方式达到目的,没办法直接进行跨级的传递。

Context可被看做一个应用执行期上下文,相当于一个容器,里面装载了很多数据。在应用开启时,Context被提供(Provider)出去,应用运行期间Context可被任何组件消费(Consumer),达到共享数据的目的。

Context虽然可以提供数据并且被消费,但是子组价并不明确其来源。在使用这种模式时,更希望Provider / Consumer能被更好的溯源。所以在开发时,通常将页面组件或着根组件作为Provider,也可指定一些特定的组件作为Provider,但需要做到心中有数。

如果在一些平行组件或不同组件树分支下的子组件需要使用到相同的数据,虽然使用Context也可以解决,但是此时就显得不伦不类,而更好的办法是使用公共状态管理器。

React Redux

Redux是一个状态管理器,本质上与React没有任何关系。在与React结合时,主要有以下痛点:

  1. Redux的状态更改无法触发React视图更新,而是需要转换成React State。
  2. React无法感知到Redux状态的更新,需要使用Redux订阅来通知React更新。

对于以上问题,react-redux的解决方式是:将store提供给组件,组件选择storestate注入到组件的props中,虽然store state无法触发React视图更新,但是props可以触发React视图的更新,致使组件重新渲染。