React与Redux Toolkit的简单使用、ts环境中一些常见问题的解决方案

15 篇文章 0 订阅
10 篇文章 1 订阅

安装

创建react+redux的TS环境(最佳实践) 无须再安装redux、redux-thunk、react-redux、immer等,默认就已经集成了@reduxjs/toolkit的Redux架构。

create-react-app react-admin --template redux-typescript

使用Redux Toolkit完成react的状态管理

demo效果演示如下
在这里插入图片描述

生成一个子reducer (createAsyncThunk, createSlice)

/**
 src/store/test/testSlice.ts

*/
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
// 异步请求
import { fetchIp } from './testAPI';

// 设置类型
export interface testState {
  value: number;
  ip: object
}
// 设置初始化state
const initialState: testState = {
  value: 1,
  ip:{}
};

// createAsyncThunk这个API可以用来设置异步方法,我们可以通过这个API来让redux支持异步。
export const getIpAsync = createAsyncThunk(
  'test/fetchIp',
  async () => {
    const response = await fetchIp();
    console.log(response)
    return response.data;
  }
);

export const testSlice = createSlice({
  name: 'test',
  initialState,
  // The `reducers` field lets us define reducers and generate associated actions
  reducers: {
    increment: (state) => {
      // Redux Toolkit允许我们在reduce中编写“突变”逻辑.  
      //它实际上不会改变状态,因为它使用Immer库, 
      //检测到“派遣状态”的变化,并产生一个全新的基于这些变化的不可变状态
      state.value += 1;
    },
  },
  // "extraReducers"字段可以让slice处理在其他地方定义的action,
  // 包括由createAsyncThunk或其他片段生成的操作.
  extraReducers: (builder) => {
    builder
      .addCase(getIpAsync.pending, (state) => {
        console.log('异步请求正在进行中!')
      })
      .addCase(getIpAsync.rejected,(state)=>{
        console.log('异步请求失败!')
      })
      .addCase(getIpAsync.fulfilled, (state, action) => {
        state.ip = action.payload;
      });
  },
});


export const { increment } = testSlice.actions;

export default testSlice.reducer;

异步方法的使用示例

/**
	src/store/testAPI.ts
*/

//在utils/request.js文件中配置请求拦截与响应拦截
import http from "../../utils/request";

// 设置一个异步请求
export function fetchIp() {
  return http({url:'/api',method:"GET"});
}

配置store (configureStore, ThunkAction, Action)

/**
	src/store/index.tsx
*/
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';

// 导入子reducer
import testReducer from './test/testSlice'

export const store = configureStore({
  // 合并子reducer
  reducer: {
    test:testReducer
  },
})

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;

使用Provider将store注入react的页面中

/**
	index.tsx
*/
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';

import { store } from './store'

ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>
  ,
  document.getElementById('root')
);

将redux.js中的useDispatch, useSelector适用于ts环境

/**
 src/hooks/index.ts
*/
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from '../store';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

react页面中使用

/**
	APP.tsx
*/
import './App.css';
import { increment,getIpAsync } from './store/test/testSlice';
import { useAppSelector,useAppDispatch } from './hooks';

function App() {
  // 获取store中的test空间的状态变量变量
  const { test } = useAppSelector(state=>state)
  // 获取dispath用于向store中派发方法
  const dispatch =useAppDispatch()
  return (
    <>
      <h1>学习@reduxjs/toolkit</h1>
      <button onClick={()=>dispatch(increment()) }>{test.value} 加一</button>
      <hr/>
      <button onClick={()=>dispatch(getIpAsync())}>查询IP</button>
    </>
  );
}

export default App;

demo文件布局如下
在这里插入图片描述

ts环境常见问题

常用的npm包在引入ts环境后会报错

当我们习惯于js的弱类型开发后,在进行ts开发会遇到一些问题,因为现在一些比较流行的有些用的是JavaScript开发,而JavaScript没有像typescript一样使用于静态类型。所以这些包就会出现一些类型问题,而为了解决这些问题,我们可以编写一些**(*.d.ts)**文件来对一些JS 库中的静态类型进行定义。在d.ts中存放一些声明,类似于C/C++的.h头文件。

TypeScript作为JavaScript的超集,在开发过程中不可避免要引用其他第三方的JavaScript的库。虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript诸如类型检查等特性功能。为了解决这个问题,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述JavaScript库和模块信息的声明文件。通过引用这个声明文件,就可以借用TypeScript的各种特性来使用库文件了。

当然,我们自己去编写可能考虑不够全面。所以,我们可以去npm官网安装对应js库的type类型包,其格式一般为 (@types/****)。例如,非常出名的 lodash包就有 @types/lodash

在这里插入图片描述
我们可以看到这个包下载量非常大。说明了,大多数人和我们一样习惯于使用成熟的第三方插件。

图片等非代码资源无法正常导入

出现这一原因是:typescript无法识别非代码资源
因此,我们可以在项目的src路径下新建一个ts声明文件

declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.gif'
declare module '*.bmp'
declare module '*.tiff'

然后在ts项目的tsconfig.json中如下代码所示导入,这样无论你在src文件夹的任意位置新建ts声明文件,都会被ts或vscode自动解析。

"include": ["src"]

当然这样直接导入src整个路径可能会出现一些问题,在此,我还是建议大家将(d.ts)类型文件,放在一个文件目录下。
例如:
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值