【react+redux】 react使用redux相关内容

首先说一下,文章中所提及的内容都是我自己的个人理解,是我理逻辑的时候,自我说服的方式,如果有问题有补充欢迎在评论区指出。

一、场景描述

为什么在react里面要使用redux,我的理解是因为想要使组件之间的通信更便捷。如下图所示,html中的信息传递只能是通过标签属性来传递,所以如果

我们有一个需求是在某一个组件中获取信息,然后在另一个组件中根据该信息来更改组件显示的内容,这就需要逐层进行信息传递。redux的作用就在于,将该信息保存为全局数据内容,这样所有组件都可以访问到,不用逐层进行信息传递。

二、相关内容介绍

2.1 typescript中的函数调用签名

函数调用签名的作用是什么:定义函数所接收到参数以及返回值的类型。

typescript 复制代码
type addFunctionType = (a: number, b: number) => number;
//这里是函数调用参数,上面定义了所接收参数以及返回值的类型。
const add: addFunctionType = (a, b) => a + b;
export default add;

2.2 问题分析

首先'react-redux'包里的useSelector用于从redux store中获取state的值,在使用该方法时,它的用法如下。

typescript 复制代码
import {useSelector} from 'react-redux';
//问题就出在这里,如果用原始的函数这里的state就要对他进行类型声明---用any也可以,减少any的使用可以对代码有一定的收益,例如减少bug
const user = useSelector( state:any => state.user);

然后我们就希望拿到这个state的类型,state就是redux中的store.getstate所获得的数据

解释一下下面所要用到的一小段代码。

typescript 复制代码
type IRootType = typeof store.getState;    //取store.getState这个函数的类型
//为什么不是 type IRootType = typeof store.getState(); 
export type FnReturnType = ReturnType<IRootType>;
//函数调用签名 它的作用是定义一个函数类型,包含函数的参数和返回类型
export const useAppSelector: TypedUseSelectorHook<FnReturnType> = useSelector;

在上述代码中我们所得到的store.getState的类型如下图所示。这个函数是用来获取state参数的,它的返回值应该是个对象,是store中所存储的全局变量--redux中存的数据。

react-redux中useSelector的作用是从redux store中获取state的值。跟直接获取的区别在于:当store中的值发生改变时,会自动渲染组件。

TypedUseSelectorHook的实现如下图所示

typescript 复制代码
interface TypedUseSelectorHook<TState> {
  //这里的<Tselected>是传入类型的意思,在后面所输入的第一个函数参数里使用 两个参数一个是selector,接收TState 类型的参数,输出Tselected类型的变量
  <TSelected>(
    selector: (state: TState) => TSelected,
    equalityFn?: EqualityFn<NoInfer<TSelected>>
  ): TSelected;
  <Selected = unknown>(
    selector: (state: TState) => Selected,
    options?: UseSelectorOptions<Selected>
  ): Selected;
}

2.3上述内容总结

二、redux相关内容

在介绍redux的内容之前,我们先分析一下需求,一般如果是这样的话,就是在所有组件都能访问到的区域创建数据。

2.1 redux的工作原理

redux的工作原理如下图所示。

图中Store是Redux的一个对象,用于保存应用的状态。--这里就是用于存储全局数据的地方,不能直接更改可以读,需要提供特征的方法进行更改。

Action就是所定义的动作类型,可以包含其他属性,用于传递额外的数据。我的理解就是定义的行为,存储的全局数据可以发生的行为需要提前定义,实际上就是定义的方法。

Reducers:就是根据Action来更新当前的State(全局数据,在react中被定义为状态)。

Dispatch: 用于向Store中发送Action。当调用store.dispatch(action)时,Store会调用reducer来处理action,更新state。

subcribe:注册监听器,当state发生变化的时候,监听器被使用。

2.2原生redux的使用

原生redux在我看来,他就是解决了一个提供所有组件全局变量的一个方案,数据改变之后他还是需要进行手动渲染。react中如果state或者props变化,他就会自动重新渲染组件,所以我们使用的方案是使用一个key state当你变化一次的时候,我们就让key变化一次,导致其重新渲染。

store.ts

typescript 复制代码
import { legacy_createStore as createStore } from "redux";
 
const reducer = (state, action) => {
  if (action.type === "increment") {
    state.num += 1;
  } else if (action.type === "decrement") {
    state.num -= 1;
  } else if (action.type === "incrementByAmount") {
    state.num += action.payload;
  } else if (action.type === "change") {
    state.amount = action.payload;
  }
  return state;
};
 
const store = createStore(reducer, {
  num: 0,
  amount: 1,
});
 
store.subscribe(() => {
  console.log("数据发生了变化");
});
 
export default store;

app.tsx

typescript 复制代码
import React, { useState } from "react";
import store from "./js/store";
function App() {
  let [key, setKey] = useState(1);
  let dispatch = store.dispatch;
  return (
    <div className="App">
      <h2>测试redux页面</h2>
      <br />
      <br />
          
      <button
        onClick={() => {
          dispatch({ type: "increment" });
          setKey(key + 1);
        }}
      >
        Increment
      </button>
         <span>{store.getState().num}</span>   
      <button
        onClick={() => {
          dispatch({ type: "decrement" });
          setKey(key + 1);
        }}
      >
        Decrement
      </button>
      <br />
         
      <input
        type="text"
        value={store.getState().amount}
        onChange={(e) => {
          dispatch({ type: "change", payload: parseInt(e.target.value) });
          setKey(key + 1);
        }}
      />
         
      <button
        onClick={() => {
          dispatch({
            type: "incrementByAmount",
            payload: store.getState().amount,
          });
          setKey(key + 1);
        }}
      >
        incrementByAmount
      </button>
    </div>
  );
}
 
export default App;

三、@reduxjs/toolkit与react-redux的相关内容

原生react在每一个使用stroe的组件文件中都要引用一次store文件,觉得很麻烦,react-redux提供了Provider组件使其只需要引用一次,使得redux更便捷。

index.tsx

typescript 复制代码
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
 
//redux的相关内容导入
import { Provider } from "react-redux";
import store from "./app/store";
const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <Provider store={store}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>
);

在@reduxjs/toolkit工具中,它将initialState、reducer以及actions整合在一起形成切片,更符合传统编程类的概念。

countSlice.ts

typescript 复制代码
import { createSlice } from "@reduxjs/toolkit";
 
export const counterSlice = createSlice({
  // 定义切片名
  name: "counter",
  // 定义切片中的全局变量
  initialState: {
    value: 0,
  },
  // reducer处理器
  reducers: {
    increment: (state) => {
      console.log(state);
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      console.log(action);
      state.value += action.payload;
    },
  },
});
 
// 生成action
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
 
export default counterSlice.reducer;

TestRedux.tsx

typescript 复制代码
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
  decrement,
  increment,
  incrementByAmount,
} from "../features/counter/counterSlice";
 
export default function TestRedux() {
  // 获取变量
  const count = useSelector((state: any) => state.counter.value);
  // 处理action
  const dispatch = useDispatch();
  const [amount, setAmount] = useState(1);
  return (
    <div>
      <h2>测试redux页面</h2>
      <br />
      <br />
          
      <button onClick={() => dispatch(increment())}>Increment</button>
         <span>{count}</span>   
      <button onClick={() => dispatch(decrement())}>Decrement</button>
      <br />
         
      <input
        type="text"
        value={amount}
        onChange={(e) => {
          setAmount(parseInt(e.target.value));
        }}
      />
         
      <button onClick={() => dispatch(incrementByAmount(amount))}>
        Decrement
      </button>
    </div>
  );
}
相关推荐
网络点点滴7 分钟前
前端与后端的区别与联系
前端
EnCi Zheng31 分钟前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen35 分钟前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技36 分钟前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人1 小时前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实1 小时前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha1 小时前
三目运算符
linux·服务器·前端
晓晨的博客1 小时前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
donecoding1 小时前
别再让 pnpm 跟着 nvm 跑了!独立安装终极指南
前端·node.js·前端工程化