【简单化】hooks+context实现redux

前言

阅读本文章,你也许需要具备react,flux,context,hooks等知识。

原由

前端开发,绕不开react,数据持久话等问题。

初始问题——react传递问题

在react中,数据子孙组件,兄弟组件,多层的数据传递,都是用props的方式来处理。
这里有两个痛点:

  • 多层数据传递的
  • 数据的订阅操作的麻烦

源码
上图为react中关于props的赋值方式

于是大家用react-redux来处理的。
使用高阶组件来注入action和store来达到数据传输和订阅操作。

延伸问题——react-redux使用的拖沓

我们知道高阶组件的注入是静态的。这就引发来一个问题,我们需要做更多。
这里的拖沓点:

  • 从sotre的数据更新到同步到view层,是需要我们进行同步的(一般写在生命周期中,通过props的比较来触发setState,以期修改view)

解决办法——hooks+context

在16版本中,引入来hooks和context的方法和概念。
利用hooks的useState即时变化特性,解决 延伸问题——react-redux使用的拖沓
利用context的多层传递特性,解决初始问题——react传递问题

代码和讲解

源码:地址

结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[ '|-- react',
' |-- index.js',
' |-- redux',
' | |-- dispatchs.js',
' | |-- index.js',
' | |-- store.js',
' | |-- actions',
' | | |-- index.js',
' | | |-- user.js',
' | |-- dispatchs',
' | |-- app.js',
' | |-- index.js',
' | |-- user.js',
' |-- router',
' | |-- index.js',
' | |-- index2.js',
' |-- styles',
' |-- initialize.scss',
' |-- mixins.scss',
' |-- variable.scss',
'' ]

主要思路

遵循flux

flux是有facebook提出的框架,我更认为是一种思想。
其保证了数据单向性,唯一性。
简而言之,存在唯一store,数据唯一改变方式为action,action触发通过dispatcher处理更新到store上。
此处不做赘述,提供:地址

hooks原则

在react文档中,有对hooks的定义,是一个函数组件。

You might have previously known these as “stateless components”. We’re now introducing the ability to use React state from these, so we prefer the name “function components”.

Hooks don’t work inside classes. But you can use them instead of writing classes.

如果你在hooks外使用class,是不合法的。

1
class [name] extends React.Component

这个地方点到为止,之后,会有一篇文章解读 在代码层面不可以的原因

context —— 同步数据

直接看代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const ReduxContext = React.createContext();
const {Provider} = ReduxContext;

const ProviderProps = (props) => {
const {children} = {...props};
const [Store, Action] = store();
console.log(Store, Action);
return (
<Provider value={{Store, Action}}>
{children}
</Provider>
)
};

export {
ProviderProps, // 插入
ReduxContext, // 读取
}

提供ProviderProps和ReduxContext两个方法。
通过useContextl来处理ReduxContext,获取返回值。
则修改ProviderProps的value值,useContextl就能获得同步。(这里,我们变解决了 延伸问题——react-redux使用的拖沓

hooks —— 保证数据唯一性

我们知道在kooks中,又是useState方法,其提供了状态及修改状态的方式。
直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let initialState = {
user: {
name: 'jack'
}
};

export default () => {
const [state, setState] = useState(initialState);

const actions = action((action) => {
const dispatchProps = dispatchs(state, action);
setState(dispatchProps)
});
return [
state,
actions
]
}

上为核心代码。
initialState:初始数据。
actions:action和dispatcher的结合器。
返回state和actions,暴露出store和action。

action —— 对action进行系统级结构调整

在actions文件中,index.js中,对action进行分类,以降低系统维护难度。
可以想想,当系统到一定的量级后,action破50+,不说多了,同名,同方式等问题就比较严重了。
多人合作开发,便会遇见命名冲突等问题。
代码如下:

1
2
3
4
5
6
7
import userAction from './user'

export default (dispatchFun) => {
return {
user: userAction(dispatchFun)
}
}

dispatch —— 对dispatcher进行系统级结构调整

当action进行分类后,数据处理也是需要系统化分类的,同样是降低维护难度。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
import userAction from './user';
import appAction from './app';

const dispatch = {
...userAction,
...appAction,
};

export default (state, action) => {
const {DATA, TYPE} = action;
return dispatch[TYPE](state, DATA)
}

运行和测试

运行

我们使用webpack进行配置,这里我们暂时注释掉eslint。
运行命令:

1
2
npm install
npm start

测试

触发方式:点击”点击”按钮
预期变化:在控制台和页面,数据和显示都发生变化。
结果

结果:数据发生变化,多了data的数据。

总结

这是我比较正式的第一篇文章,主要是讲述如何使用context和hooks的useState来实现redux。
欢迎👏各位朋友交流,不足之处还望指教。