【React】TS项目配置Redux

前提条件

在React中使用Redux,官方要求安装两个插件,Redux Toolkitreact-redux

Redux Toolkit(RTK): 官方推荐编写Redux逻辑的方式,是一套工具的集合集,简化书写方式

  1. 简化 store 的配置方式
  2. 内置 immer 支持可变式状态修改
  3. 内置 thunk 更好的异步创建

react-redux:用来链接 Redux 和 React组件的中间件。

安装

npm i @reduxjs/toolkit react-redux

浏览器插件 - Redux DevTools(推荐但不强制使用)

下载并启用插件
在这里插入图片描述

控制台找到redux选项
在这里插入图片描述

配置

目录结构

src 下创建 store,其中 index.ts/index.js 作为modules中所有store的集合
在这里插入图片描述

store/index.ts配置

import { configureStore } from '@reduxjs/toolkit'const store = configureStore({reducer: {},
})// 后续使用useSelector时参数state的类型
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatchexport default store

index.ts 或 main.ts中注册store

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
// 添加如下
import store from './app/store'
import { Provider } from 'react-redux'ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById('root')
)

至此已经全局注册了Redux

配置

这里以计数器为例,在store/modules中创建counterSlice.js/ts

同步配置

import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'export interface CounterState {value: number
}const initialState: CounterState = {value: 0,
}export const counterSlice = createSlice({name: 'counter',initialState,reducers: {increment: (state:CounterState) => {state.value += 1},decrement: (state:CounterState) => {state.value -= 1},},
})export default counterSlice.reducer

异步配置

import { createSlice,createAsyncThunk } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'export interface CounterState {value: number
}
const initialState: CounterState = {value: 0,
}export const counterSlice = createSlice({name: 'counter',initialState,// 同步操作reducers: {......},// 异步操作extraReducers(builder){// 这里的payload就是incrementAsync的返回值builder.addCase(incrementAsync.fulfilled,(state,{payload})=>{state.value += payload})}
})
// 定义异步函数
export const incrementAsync = createAsyncThunk<number>("incrementAsync",async(p:number)=>{const res = await new Promise<number>(r=>{setTimeout(() => {r(p)}, 1000);})return res
})
export default counterSlice.reducer

store/index.ts 中注册

import { configureStore } from "@reduxjs/toolkit";
// 引入counterSlice.ts
import counterStore  from "./modules/counterSlice";const store = configureStore({reducer:{// 注册,注意名字要与counterSlice.ts中的name一致counter:counterStore}
})export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatchexport default store 

再次查看Redux Tools工具,已经发现value
在这里插入图片描述

使用

// useSelect用于选择操作哪个store
// useDispatch用于生成实例,该实例可以调用reducers的function
import { useSelector, useDispatch } from "react-redux" // 引入index中的RootState类型  js项目不需要
import { AppDispatch, RootState } from "@/store" // 引入functions
import { decrement, increment, incrementAsync } from "@/store/modules/counterSlice" const Demo = () => {const count = useSelector((state: RootState) => state.counter.value)const dispatch: AppDispatch = useDispatch() // 异步函数必须加AppDispatch类型,否则报错,同步可以不添加return (<><div className="navbar_top"></div><div>{count}</div><button onClick={() => dispatch(increment({ value: 2 }))}>+2</button><button onClick={() => dispatch(incrementAsync(2))}>+2</button><button onClick={() => dispatch(decrement())}>-1</button></>)
}
export default Demo

操作后通过工具发现value已经改变
在这里插入图片描述