redux的快速开始
安装环境依赖
| |
| npx create-react-app 项目名 --template typescript |
| |
| npm install @reduxjs/toolkit react-redux |
| |
| npm install axios |
复制
创建 Redux State Slice
创建 src/store/modules/channelStore 文件(文件所放置的位置可以自定义,最好有一个好的结构)。在该文件中从 Redux Toolkit 引入 createSlice API。
创建 slice 需要一个字符串名称来标识切片、一个初始 state 以及一个或多个定义了该如何更新 state 的 reducer 函数。slice 创建后 ,我们可以导出 slice 中生成的 Redux action creators 和 reducer 函数。
| import { createSlice } from "@reduxjs/toolkit" |
| import { AppDispatch } from "../index"; |
| import axios, {AxiosResponse} from "axios" |
| interface dataType { |
| id: number, |
| name: string, |
| } |
| |
| interface ChannelState { |
| channelList: dataType[]; |
| } |
| interface ResponseType { |
| data: { |
| channels: dataType[]; |
| }; |
| } |
| const initialState: ChannelState = { |
| channelList: [{id: 1, name: "前端"}] |
| } |
| const channelStore = createSlice({ |
| name: "channel", |
| initialState, |
| reducers: { |
| changeChannel: (state, action: PayloadAction<dataType[]>) => { |
| state.channelList = action.payload |
| } |
| } |
| }) |
| |
| const { changeChannel } = channelStore.actions |
| |
| export const getChannelList = () => { |
| return async (dispatch: AppDispatch) => { |
| const res:AxiosResponse<ResponseType> = await axios.get("http://geek.itheima.net/v1_0/channels") |
| const data = await res.data.data.channels; |
| dispatch(changeChannel(data)) |
| } |
| } |
| export default channelStore.reducer |
复制
初始状态initialState说明
对于redux管理的初始状态initialState你需要的所有状态,比如name,age什么的
| interface dataType { |
| id: number, |
| name: string, |
| } |
| interface ChannelState { |
| channelList: dataType[]; |
| |
| |
| } |
| const initialState: ChannelState = { |
| channelList: [{id: 1, name: "前端"}], |
| |
| |
| } |
复制
reducers状态管理函数
对于reducer中的状态管理函数 changeChannel: (state, action: PayloadAction<dataType[]>) => {
state.channelList = action.payload
}来说, state用来管理你所定义的状态,而action能够接收你所传递过来的参数 action中定义了type的playload两个参数,playload能够接收到你所传递过来的参数
| changeChannel: (state, action: PayloadAction<dataType[]>) => { |
| state.channelList = action.payload |
| } |
| } |
| |
| export type PayloadAction<P = void, T extends string = string, M = never, E = never> = { |
| payload: P; |
| type: T; |
| } & ([M] extends [never] ? {} : { |
| meta: M; |
| }) & ([E] extends [never] ? {} : { |
| error: E; |
| }); |
| action: PayloadAction<dataType[]>会将PayloadActiion中的泛型传递给payload 这样使数据的类型可控 |
复制
关于axios异步获取数据的类型说明
dispatch调用定义的函数方法
| |
| export const getChannelList = () => { |
| return async (dispatch: AppDispatch) => { |
| |
| const res:AxiosResponse<ResponseType> = await axios.get("http://geek.itheima.net/v1_0/channels") |
| const data = await res.data.data.channels; |
| dispatch(changeChannel(data)) |
| } |
| } |
复制
AxiosResponse说明如下 将ResponseType赋予给与的数据
如何你开始不清楚后端返回的数据类型可以暂时写成any,然后根据后端所提供数据编写相应的数据类型
| export interface AxiosResponse<T = any, D = any> { |
| data: T; |
| status: number; |
| statusText: string; |
| headers: RawAxiosResponseHeaders | AxiosResponseHeaders; |
| config: InternalAxiosRequestConfig<D>; |
| request?: any; |
| } |
| |
复制
创建Redux Store
在src/store/index.tsx中编写导出的store数据
| import { configureStore } from "@reduxjs/toolkit"; |
| import channelStore from "./modules/channelStore"; |
| const store = configureStore({ |
| reducer: { |
| channel: channelStore |
| }, |
| }); |
| |
| |
| export type RootState = ReturnType<typeof store.getState> |
| |
| export type AppDispatch = typeof store.dispatch |
| export default store; |
复制
定义Hook类型 --以便在react项目中调用
在src中定义 hooks.tsx
尽管你可以将 RootState 和 AppDispatch 类型导入每个组件, 更好的方式是创建 useDispatch 和 useSelector 钩子的类型定义,以便在你的应用程序中使用 有几个重要的原因:
- 对于 useSelector ,它不需要你每次输入(state: RootState)
- 对于 useDispatch ,默认的 Dispatch 类型不知道 thunk 。为了正确调度 thunk ,你需要使用 store 中包含 thunk 中间件类型的特定自定义 AppDispatch 类型,并将其与 useDispatch 一起使用。添加一个预先输入的 useDispatch 钩子可以防止你忘记在需要的地方导入 AppDispatch。
| import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' |
| import type { RootState, AppDispatch } from './index' |
| |
| |
| export const useAppDispatch: () => AppDispatch = useDispatch |
| export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector |
复制
为 React 提供 Redux Store
创建 store 后,便可以在 React 组件中使用它。
在 src/index.js 中引入我们刚刚创建的 store , 通过 React-Redux 的 将 包裹起来,并将 store 作为 prop 传入。
| root.render( |
| |
| <Provider store={store}> |
| <App /> |
| </Provider> |
| ); |
复制
在react中使用redux
| import { useEffect } from "react"; |
| import { useAppSelector, useAppDispatch } from "../store/hooks"; |
| import {getChannelList } from "../store/modules/channelStore"; |
| const StoreText = () => { |
| const {channelList} = useAppSelector((state) => state.channel); |
| const dispatch = useAppDispatch(); |
| |
| |
| useEffect(() => { |
| dispatch(getChannelList()) |
| }, []); |
| return (<div> |
| |
| <ul> |
| {channelList.map((item) => ( |
| <li key={item.id}>{item.name}</li> |
| ))} |
| </ul> |
| </div>); |
| }; |
| |
| export default StoreText; |
复制