前言
Redux
的究极状态形态基本就是 DVA
,也就是封装自 Redux + Redux-saga
。不过,我并没有使用 DVA
,因为项目较早。我自己也有自己的封装,只不过一开始的时候,并没有 DVA
那么完整的概念,后来参考 DVA
以后,我重新写了个 mini
库,代码大约 120 行左右,已经在公司内部全面使用。
这个库实现了 page
(页面)和 model
的自动加载,省去了一个一个 import model
和 import page
的痛苦,具体的,可以阅读代码和 Readme
.
不过,本文并不是讲述如何构建一个类 DVA
状态管理库,我说过,我厌倦了 Redux
。
分析与思考
在我们刚刚学习 React
的时候,很快就能接受了 状态机 和 组件化 的思想,并且很快能够写出一个 React
程序。
import React from 'react'
class App extends React.component{
state={
count:0
}
handleClick = ()=>{
this.setState({
count:this.state.count + 1
})
}
render(){
return (<div onClick={this.handleClick}>
{this.state.count}
</div>)
}
}
我们将一个一个组件进行封装,每个组件都有自己的状态,相互不污染,相互不限制,这看似是一件美好的事情。
但是,当我们哪怕是做一个 TODOLIST
就会发现,我们必须要进行 状态共享。状态共享对于React
来说是一个大难题,为了解决这个问题,人们从开始的 Flux
架构,一直到现在广为流传的 Redux / Mobx
架构。
但是,我认为这无疑是给 React
增加了很多概念。我知道我知道,你 或许一定肯定必须是 一个 Redux
究极粉丝,但是认真想一下,状态共享真的需要引入这么多概念吗?
最大痛点:概念过多、学习陡峭
这一直是 Redux
的一个毛病,我们就来看看要完整的使用 Redux
我们必须要掌握一些什么东西:
- 理解
Redux
全局状态机的机制,action
,reducer
,selector
等概念 - 巨大状态机的拆分,使用
combindReducer( )
函数 - 需要掌握一些中间件,目前最佳的是
redux-saga
- 使用
react-redux
库,书写mapStateToProps
等函数 - 想要书写一个完美的
react-redux
应用,上述的四点,已经成为现在的一个指标。虽然类似如DVA
等库已经帮我们进一步的封装,屏蔽了上述的一些细节,但是我们的学习成本依旧不低。
轻量化状态管理
作者 Dan
其实已经意识到了这一点,并且在最近的 React
版本中构建了一套全新的 Context API
,想通过这一套机制,逐步的代替 Redux
。
今天,我就来给大家介绍一种轻量级的状态管理方式,为什么我说是轻量级?
- 使用最初版本的
setState()
去更新我们的 全局状态 - 使用
class
的方式,对 全局状态 进行切分,而不是引入类似model
等方式
因为原本就是setState
,因此我们无需引入任何中间件就可以处理副作用。
那么,就让我们引入我最近在研(抄)究(袭)的轮子:215566435/rectx
Controller 类
等等,controller
是什么鬼?这是在写后台么!?放心,不是,只是一个简单的概念而已。
Controller
用于存放一堆逻辑相关的状态与更新状态的逻辑等等,以 class
形式组织
我们直接来看代码:
import { Controller } from 'rectx'
class LikeController extends Controller {
state = {
isLike: false,
isMount: false
}
handleClick = () => {
this.setState({
isLike: !this.state.isLike
})
}
}
非常简单的几步,就完成了一个 Controller
的书写
-
State
:用于存放初始状态 -
this.setState
:你没看错,这里的this.setState
与React
的this.setState
是一样的,作用就是更新状态
Listen 组件
Listen
组件是一个抽象组件,封装自 context.comsumer
,用于传递 Controller
的状态,方法等。
const Like = () => (
<Listen
to={[LikeController]}
didMount={like => {
like.setState({ isMount: true })
}}
>
{like => (
<div>
<button
onClick={() => like.handleClick()}
>
Click me
</button>
<div>
{like.state.isMount ?
'component being loaded' :
'component not loaded'}
</div>
<div>
{like.state.isLike ?
'I love you' :
'I hate you'}
</div>
</div>
)}
</Listen>
)
- 这是一个叫做
Like
的 无状态组件 -
Listen
组件有一个props
叫to
,to
接收一个或者多个controller
,并以render props
的形式渲染子组件 -
render props
函数的参数,就是我们刚刚输入进Listen
组件的实例 -
Listen
组件还有一个didMount
函数,用于监听被订阅组件的挂载是否成功
是不是开始明白了?Listen
组件能够依赖注入式的将我们的 Controller
输入到组件之中,然后我们的组件就可以很好的使用我们的 Controller
中的方法、状态,并且,每个 Controller
提供的状态是完全隔离的!
Provider 组件
与 react-redux
的 provider
组件类似,但是无需输入参数
render(
<Provider>
<Like />
</Provider>,
document.getElementById("root")
);
好了,这样就已经完成了!如果你想要看真实的效果,请去:l970jx93pz - CodeSandbox
是不是非常的简单?回头看一下我们的状态管理
我们引入了一个 Controller
的概念,对我们的状态进行管理。这样的好处在于:
- 现在,我们将全局的
store
拆分成了一个一个的类,这些类可以放在不同的文件中,形成天然的模块化,我们还可以对这些类进行统一的封装,管理完全的面向对象化 - 我们将
state
聚合在一个类中,更新类的方式使用为原本React
的setState
,使得开发人员只要掌握了React
,那么只需要再掌握Rectx
的几个「React
组件的用法」,就可以完成对状态的管理 - 无需中间件就可以完成对副作用的控制:嘿~因为我们使用的是
setState
~
当然,我认为,Rectx
还需要进一步的封装才能更加好用,我也将使用 rectx
重写我的一些应用。
仓库地址:rectx
喜欢的给点星星哦