当前位置: 首页 > article >正文

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

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

一、场景描述

为什么在react里面要使用redux,我的理解是因为想要使组件之间的通信更便捷。如下图所示,html中的信息传递只能是通过标签属性来传递,所以如果
我们有一个需求是在某一个组件中获取信息,然后在另一个组件中根据该信息来更改组件显示的内容,这就需要逐层进行信息传递。redux的作用就在于,将该信息保存为全局数据内容,这样所有组件都可以访问到,不用逐层进行信息传递。
在这里插入图片描述

二、相关内容介绍

2.1 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的值,在使用该方法时,它的用法如下。

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

然后我们就希望拿到这个state的类型,state就是redux中的store.getstate所获得的数据
解释一下下面所要用到的一小段代码。

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的实现如下图所示

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

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

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

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

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

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>
  );
}

在这里插入图片描述


http://www.kler.cn/a/528800.html

相关文章:

  • 3.Spring-事务
  • vue2项目(一)
  • 大模型培训讲师老师叶梓分享:DeepSeek多模态大模型janus初探
  • 如何使用tushare pro获取股票数据——附爬虫代码以及tushare积分获取方式
  • 【gRPC-gateway】option定义规则及HttpBody响应
  • HTML(快速入门)
  • langchain 实现多智能体多轮对话
  • 什么情况下,C#需要手动进行资源分配和释放?什么又是非托管资源?
  • 无心剑七绝《深度求索》
  • 数据密码解锁之DeepSeek 和其他 AI 大模型对比的神秘面纱
  • 解锁Linux共享内存:进程通信的极速引擎
  • 人机交互系统实验二 图形用户界面的设计
  • 代码练习3
  • 知识图谱中如何做种子对齐?
  • 步进电机的型号和分类
  • 浅析CDN安全策略防范
  • SCRM系统如何提升客户管理及业务协同的效率与价值
  • Python-基于PyQt5,wordcloud,pillow,numpy,os,sys的智能词云生成器
  • 2025.2.1——四、php_rce RCE漏洞|PHP框架
  • 【08-飞线和布线与输出文件】
  • STM32 TIM编码器接口测速
  • 大模型本地部署使用方法(Ollama脚手架工具、FisherAI浏览器大模型插件、AnythingLLM大模型集成应用平台)
  • 【技海登峰】Kafka漫谈系列(一)Kafka服务集群的核心组件
  • 力扣第149场双周赛
  • DeepSeek或准备适配国产GPU,将推动国产芯片生态发展
  • 2024第十五届蓝桥杯网安赛道省赛题目--cc(CyberChef)/crypto