redux结合typescript进行状态管理

redux的快速开始

安装环境依赖

//使用CRA创建react项目 使用typescipt进行编写
npx create-react-app 项目名 --template typescript
//安装redux环境依赖
npm install @reduxjs/toolkit react-redux
//安装axios支持异步操作
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[];
    //name: string,
    //age: number
}
const initialState: ChannelState = {
    channelList: [{id: 1, name: "前端"}],
    //name: '123',
    //age: 17
}
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
        }
    }
 //点击action  crl + 鼠标点击就可以查看关于其的说明
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调用定义的函数方法

//dispatch: AppDispatch 类型后面会进行说明
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
  },
});

// 从 store 本身推断出 `RootState` 和 `AppDispatch` 类型
export type RootState = ReturnType<typeof store.getState>
// 推断出类型: {posts: PostsState, comments: CommentsState, users: UsersState}
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'

// 在整个应用程序中使用,而不是简单的 `useDispatch` 和 `useSelector`
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;
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值