IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React与Redux Toolkit的简单使用、ts环境中一些常见问题的解决方案 -> 正文阅读

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

安装

创建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)类型文件,放在一个文件目录下。
例如:
在这里插入图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:37:53  更:2021-12-11 15:40:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:53:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码