安装依赖
执行以下命令安装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, registeredfunction createApp(options?: any) {const { models } = optionsif (process.env.NODE_ENV === 'development') {// 是否打印redux变化的日志options.onAction = [createLogger()]}app = create({ ...options })app.use(createLoading({}))if (!registered) models.forEach((model) => app.model(model))registered = trueapp.start()store = app._storeapp.getStore = () => storedispatch = store.dispatchapp.dispatch = dispatchreturn 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'; // 引入modelsconst 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中的数据```typescriptimport { 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: stringcount: 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); // 获取到countconst 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
最终效果如下

