安装依赖
执行以下命令安装Redux和依赖包
yarn add react-redux redux dva-core dva redux-logger dva-loading
1、增加store的目录文件
目标=> src/store/index.ts
├─store // 创建目录
| ├─dva.ts
| ├─index.ts
往[ src/store/dva.ts ] 添加内容
import { create } from 'dva-core'
import { createLogger } from 'redux-logger'
import createLoading from 'dva-loading'
let app, store, dispatch, registered
function createApp(options?: any) {
const { models } = options
if (process.env.NODE_ENV === 'development') {
// 是否打印redux变化的日志
options.onAction = [createLogger()]
}
app = create({ ...options })
app.use(createLoading({}))
if (!registered) models.forEach((model) => app.model(model))
registered = true
app.start()
store = app._store
app.getStore = () => store
dispatch = store.dispatch
app.dispatch = dispatch
return app
}
export default {
createApp,
getDispatch() {
return app.dispatch
}
}
往[ src/store/index.ts ] 添加内容
引入src/store/dva.ts的文件
import dva from './dva';
const dvaApp = dva.createApp();
const store = dvaApp.getStore();
export default store;
2、创建models文件夹管理数据
目标=> src/models/index.ts
├─models // 增加目录models
| ├─app.ts // 使用app为例
| ├─connect.d.ts // 存放公共数据的类型
| ├─index.ts // 作为统一出口
往TS类型文件 [ src/models/connect.d.ts ] 添加内容
import { AnyAction } from 'redux';
import { EffectsCommandMap } from 'dva';
// import { UserModelState } from './user'; 其他model的文件可以导入这里,统一导出
// export { UserModelState };
export interface Loading {
global: boolean;
effects: { [key: string]: boolean | undefined };
models: {
global?: boolean;
menu?: boolean;
setting?: boolean;
user?: boolean;
};
}
export interface ConnectState {
loading: Loading;
// user: UserModelState;
}
export type Effect = (
action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: ConnectState) => T) => T },
) => void;
/**
* @type P: Type of payload
* @type C: Type of callback
*/
export type Dispatch = <P = any, C = (payload: P) => void>(action: {
type: string;
payload?: P;
callback?: C;
[key: string]: any;
}) => any;
// export interface ConnectProps<T = {}> extends Partial<RouterTypes<Route, T>> {
export interface ConnectProps {
dispatch: Dispatch;
}
往文件 [ src/models/app.ts ] 添加内容
import { Effect } from "dva";
import { Reducer } from "redux";
export interface AppModelState {
name: string // 定义state的变量
}
export interface AppModelType {
namespace: "app"; // 这个名字调用这里的方法的时候需要使用
/**
* 例如:在页面中调用
* useDispatch({
* type: "app/fetchApp"
* })
*/
state: AppModelState;
effects: {
fetchApp: Effect;
};
reducers: {
saveApp: Reducer<AppModelState>;
};
}
const initState: AppModelState = {
name: 'nangdie' // 需要管理的公共值
// ...
};
const AppModel: AppModelType = {
namespace: "app",
state: initState,
effects: {
*fetchApp(_, { call, put }) { // 可以异步执行
const result = yield call(/* 放入请求函数,Promise函数 */);
yield put({
type: "saveApp", // 将返回的调用saveApp进行保存
payload: result
});
}
},
reducers: {
saveApp(state = initState, action) { return { ...state, ...action } } // 保存到state上。
}
};
export default AppModel;
往文件 [ src/models/index.ts ] 添加内容
import app from "./app";
// import user from "./user";
// ...
export default [app , /*user*/]; //导出一个数组,里面包含多个模块
3、对所有文件进行关联
将store文件和models文件进行关联
修改 [ src/store/index.ts ] 的内容,导入models
import dva from './dva';
import models from '../models/index'; // 引入models
const dvaApp = dva.createApp({
initialState: {},
models // 加入models , 这是一个数组,可包含多个模块
});
const store = dvaApp.getStore();
export default store;
将 [ src/store/index.ts ]加入到 [ src/app.tsx ]中使用(正式启用)
- 注意:如果不是app.tsx 需要你把 app.ts 的文件名改成 app.tsx ,然后重新编译即可。 ```typescript import React, { Component } from “react”; import { Provider } from “react-redux”; //新增 import store from “./store/index”; // 新增 import “./app.scss”;
class App extends Component {
componentDidMount() { }
// render() { return this.props.children }
render() {
return
export default App;
<a name="OebHt"></a>
### 4、接下来你可以在组件和页面之间使用了
> 这里可能有人问,为什么不用connect ? 因为connect在Taro有兼容问题,可能导致数据没法更新
<a name="C4TOW"></a>
#### 获取redux中的数据
```typescript
import { useSelector } from "react-redux";
const appName = useSelector(state => state.app.name);
改变redux中的数据
import { useDispatch } from "react-redux";
const dispatch = useDispatch()
// 调用effects的函数
dispatch({
type: "app/fetchApp",
payload: '新的参数1'
})
// 调用reducers的函数
dispatch({
type: "app/saveApp",
payload: '新的参数2'
})
5、例子:使用redux实现计数
在 [ src/models/app.ts ] 中添加count
import { Effect } from "dva";
import { Reducer } from "redux";
export interface AppModelState {
name: string
count: number //新增
}
export interface AppModelType {
namespace: "app";
state: AppModelState;
effects: {
fetchApp: Effect;
};
reducers: {
saveApp: Reducer<AppModelState>;
saveCount: Reducer<AppModelState>;
};
}
const initState: AppModelState = {
name: 'nangdie',
count: 0 //新增
};
const AppModel: AppModelType = {
namespace: "app",
state: initState,
effects: {
*fetchApp(_, { call, put }) {
const result = yield call(/* 放入请求函数,Promise函数 */);
yield put({
type: "saveApp",
payload: result
});
},
},
reducers: {
saveApp(state = initState, action) { return { ...state, ...action.payload } },
saveCount(state = initState, action) { // 新增方法,将接受到的数字进行保存
console.log(action,'.action')
return {
...state,
count: action.payload
}
}
}
};
export default AppModel;
修改 [ src/pages/index/index.tsx ]
将该文件下的默认数据清空,修改成Hooks的方式
import React, { Component, useState } from 'react'
import { View, Text } from '@tarojs/components'
import { useSelector, useDispatch } from "react-redux"; //引入
import { AtButton } from 'taro-ui'
const Index = () => {
const count = useSelector(state => state.app.count); // 获取到count
const dispatch = useDispatch()
const addCount = () => {
dispatch({ // 调用方法
type: 'app/saveCount',
payload: count + 1
})
}
return <View>
<View>当前数字: {count}</View>
<AtButton type="primary" onClick={addCount}> 加1</AtButton>
</View>
}
export default Index
模拟异步请求数据
只要写在effects里即可
import { showToast, hideLoading } from "@tarojs/taro"; //显示状态
*fetchCount(_, { call, put }) {
// 模拟请求 , 假装我在等待服务器返回结果
const getCount = () => new Promise((resolve) => {
showToast({
title: "请求中...",
mask: true,
icon: "loading"
});
setTimeout(() => {
resolve(new Date().getTime())
hideLoading();
}, 3000);
})
const result = yield call(getCount)
yield put({ // 调用保存
type: "saveCount",
payload: result
})
}
在 [ src/models/app.ts ] 中添加一个方法,完整的代码
import { Effect } from "dva";
import { Reducer } from "redux";
import { showToast, hideLoading } from "@tarojs/taro";
export interface AppModelState {
name: string // 定义state的变量
count: number
}
export interface AppModelType {
namespace: "app"; // 这个名字调用这里的方法的时候需要使用
/**
* 例如:在页面中调用
* useDispatch({
* type: "app/fetchApp"
* })
*/
state: AppModelState;
effects: {
fetchApp: Effect;
fetchCount: Effect;
};
reducers: {
saveApp: Reducer<AppModelState>;
saveCount: Reducer<AppModelState>;
};
}
const initState: AppModelState = {
name: 'nangdie',
count: 0
};
const AppModel: AppModelType = {
namespace: "app",
state: initState,
effects: {
*fetchApp(_, { call, put }) {
const result = yield call(/* 放入请求函数,Promise函数 */);
yield put({
type: "saveApp",
payload: result
});
},
*fetchCount(_, { call, put }) {
const getCount = () => new Promise((resolve) => { //模拟请求 , 假装我在等待服务器返回结果
showToast({
title: "请求中...",
mask: true,
icon: "loading"
});
setTimeout(() => {
resolve(new Date().getTime())
hideLoading();
}, 3000);
})
const result = yield call(getCount)
yield put({ // 调用保存
type: "saveCount",
payload: result
})
}
},
reducers: {
saveApp(state = initState, action) { return { ...state, ...action.payload } },
saveCount(state = initState, action) {
console.log(action, '.action')
return {
...state,
count: action.payload
}
}
}
};
export default AppModel;
在 [ src/pages/index/index.tsx ] 中使用
import React, { Component, useState } from 'react'
import { View, Text } from '@tarojs/components'
import { useSelector, useDispatch } from "react-redux";
import { AtButton } from 'taro-ui'
const Index = () => {
const count = useSelector(state => state.app.count);
const dispatch = useDispatch()
const addCount = () => {
dispatch({
type: 'app/saveCount',
payload: count + 1
})
}
const requestCount = () => {
dispatch({ type: 'app/fetchCount' })
}
return <View>
<View>当前数字: {count}</View>
<AtButton type="primary" onClick={addCount}> 加1</AtButton>
<AtButton onClick={requestCount}> 模拟请求</AtButton>
</View>
}
export default Index