这是在稀土上跟一位大佬做的。
使用 Redux 有很多好处。它可以帮助您编写行为一致、在不同环境(客户端、服务器和本机)中运行且易于测试的应用程序。集中管理应用程序的状态和逻辑可以实现强大的功能,如撤销/重做、状态持久化等。 Redux 通常用于管理复杂的应用程序状态。当您的应用程序具有大量交互数据、需要在多个组件之间共享数据或状态时,使用 Redux 可以帮助您更好地管理和维护应用程序状态。此外,当您需要跟踪应用程序状态的历史记录并实现撤销/重做等功能时,Redux 也非常有用。
实时性数据存储
我们通过 redux 进行数据状态管理,为了避免繁琐的操作,采用 rc-redux-model 进行辅助开发
1. 安装
让我们先来安装一下
npm install redux
npm install rc-redux-model --save-dev // 👉 安装这个库,简便redux操作
npm install redux-logger --save-dev // 👉 安装这个库,让我们在控制台看到redux数据
安装完成后,我们在 app/renderer 文件夹下,新增一个名为 store 的文件夹,存放着所有 redux model 相关的代码文件。在里面新增一个文件名为 index.ts,该文件主要引入我们所有的 model,经过 redux 的 API,导出一颗完整的数据状态树。(看下面代码注释)
// renderer/store/index.ts
import logger from 'redux-logger';
import RcReduxModel from 'rc-redux-model';
import { createStore, applyMiddleware, combineReducers } from 'redux';
// 👇 引入我们写好的 model
import globalModel from './globalModel';
// 👇 这里只需要调用 RcReduxModel 实例化一下得到最后的 reduxModel
const reduxModel = new RcReduxModel([globalModel]);
// 👇 无侵入式的使用 Redux,即使你写最原始的 reducer 也照样支持
const reducerList = combineReducers(reduxModel.reducers);
export default createStore(reducerList, applyMiddleware(reduxModel.thunk, logger));
上面我们引入了 ./globalModel,那么我们在 store 文件夹下,追加一份 globalModel.ts 文件。
// renderer/store/globalModel.ts
const globalModel = {
namespace: 'globalModel',
openSeamlessImmutable: true,
state: {
appName: '简历应用平台',
},
};
export default globalModel;
通过 rc-redux-model 官方文档介绍:在 model 中,action 以及 reducer 我们均可忽略不写。只需要定义好 state 值即可。
到目前为止,我们已经将 redux 文件信息创建好了,接下来在项目中使用,不过在使用前,先捋一下 react、redux、react-redux 的关系。
2. 为什么要用 react-redux
如果你还记得阿宽前面介绍的 react 数据流知识,想必你还有印象:当多个组件需要进行数据共享,交换双方的数据,唯一的解决方案就是:提升 state,将原本兄弟组件的 state 提升到共有的父组件中管理,由父组件向下传递数据,子组件进行处理,通过回调函数回传修改 state,这样的 state 一定程度上是响应式的。redux 也是这样的原理!
要知道 redux 是不区分技术栈的,意味着你也可以在 vue 中使用,只是我们经常搭配套餐使用 react。如上述的代码,我们通过 createStore 导出了数据状态树后,在组件中,我们如何得到数据值呢?只能通过 redux 提供的 store.getState() API,意味着我们每个组件都需要写:(下面为伪代码)
import store from './store/index.ts';
function Home() {
// 👇 每个组件都需要这么写才能拿到数据
const state = store.getState();
}
另一种方式是你可以在根组件获取 store,通过 Props 层层传递,如果你中间组件断层,没传递 Props,就会导致下层组件获取不到值,为了在使用上简洁方便,我们才引入了 react-redux 库。
让我们安装一下
npm install react-redux
3. 在组件中使用 redux
当你捋清楚三者关系并安装 react-redux 之后,接下来在组件中使用 redux 不再是困难的事。我们将经过 createStore 生成的 store 挂载到 react-redux 提供的 Provider 组件上,这个 Provider 的工作任务是:通过 context 向子组件提供 store。
多说无益,上手试试,我们进入根组件 app.tsx 将其进行修改
import React from 'react';
import ReactDOM from 'react-dom';
import Router from './router';
// 👇 引入 store
import store from './store';
// 引入 Provider
import { Provider } from 'react-redux';
function App() {
return (
<Provider store={store}>
<Router />
</Provider>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
刷新一下页面,没有发生报错,也不会出现白屏,接下来我们在首页入口模块获取一下 redux 中的数据吧~ 上面我们已经给了一个初始值,appName="简历应用平台",我们修改一下首页模块的 index.tsx
// renderer/container/root/index.tsx
import { useSelector } from 'react-redux';
function Root() {
const appName = useSelector((state: any) => state.globalModel.appName);
console.log('appName = ', appName);
}
刷新一下页面,打开控制台,看看打印的数据,很完美符合我们的预期。
4. 在组件中修改 redux
既然可以获取 redux 数据值,自然而然地,我们也需要修改 redux 的值。在redux 官方文档中,很明确提到:唯一改变 state 的方法就是触发 action。
通过 dispatch 发起一个 action 就能修改 state 值,但仔细一想,每个 state,都对应一个 action,在简历这种多 state 值下,这是不是很麻烦呢?得益于 rc-redux-model,它提供一个 action API,只需记住一个 action,就能修改 state 的任意值。接下来我们来修改一下
// renderer/container/root/index.tsx
import { useSelector, useDispatch } from 'react-redux';
function Root() {
const dispatch = useDispatch();
const appName = useSelector((state: any) => state.globalModel.appName);
useEffect(() => {
setTimeout(() => {
console.log('3s 后修改...');
dispatch({
type: 'globalModel/setStore',
payload: {
key: 'appName',
values: 'visResumeMook',
},
});
}, 3000);
}, []);
useEffect(() => {
console.log('appName = ', appName);
}, [appName]);
}
解读一下上面代码,我们在生命周期 didMount 中写了一段延时方法,在 3s 之后修改 appName,紧接着对 appName 进行监听,当它修改时,打印当前最新的值。小伙伴们猜测一下,3s 后数据是不是会发生改变呢?刷新页面,打开控制台,发现一切如我们预期一致。
至此,我们能够已经能够项目中使用 redux 进行实时性数据的存储,更多的使用在接下来的实战过程中会讲到。