React低代码项目:Redux 状态管理

吐司问卷:Redux 状态管理

Date: February 18, 2025 5:37 PM (GMT+8)


Redux 管理用户信息

命名规范:

以 Info 结尾表示获取Reudx信息,比如 useGetUserInfo.ts

以 data 结尾表示获取服务端信息,比如 useLoadQuestionData



采用 Redux 管理用户信息

Redux store 设计:

src/store/index.ts

import { configureStore } from '@reduxjs/toolkit'
import userReducer, { UserStateType } from './userReducer'export type StateType = {user: UserStateType
}export default configureStore({reducer: {user: userReducer,},
})

userReducer 开发:

src/store/userReducer.ts

import { createSlice, PayloadAction } from '@reduxjs/toolkit'export type UserStateType = {username: stringnickname: string
}const INIT_STATE: UserStateType = {username: '',nickname: '',
}export const userSlice = createSlice({name: 'user',initialState: INIT_STATE,reducers: {loginReducer: (state: UserStateType,action: PayloadAction<UserStateType>) => {return action.payload},logoutReducer: () => {return INIT_STATE},},
})export const { loginReducer, logoutReducer } = userSlice.actions
export default userSlice.reducer

src/index.ts

 import React from 'react'import ReactDOM from 'react-dom/client'
+import { Provider } from 'react-redux'
+import store from './store'import App from './App'const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)root.render(<React.StrictMode>
-    <App />
+    <Provider store={store}>
+      <App />
+    </Provider></React.StrictMode>)


点击Logo跳转优化

**需求:**原本点击 Logo 会跳转到 home 页。现在需要根据是否有用户信息,进行区分判断。

如果有用户信息,点击 Logo 则跳转到管理页面。没有则到 home 页面。

src/component/Logo.tsx

-import React, { FC } from 'react'
+import React, { FC, useState, useEffect } from 'react'import { Space, Typography } from 'antd'import { BlockOutlined } from '@ant-design/icons'import { Link } from 'react-router-dom'
+import useGetUserInfo from '../hooks/useGetUserInfo'
+import { HOME_PATHNAME, MANAGE_INDEX_PATHNAME } from '../router/index'import styles from './Logo.module.scss'const { Title } = Typographyconst Logo: FC = () => {
+  const { username } = useGetUserInfo()
+  const [pathname, setPathname] = useState<string>(HOME_PATHNAME)
+  useEffect(() => {
+    if (username) {
+      setPathname(MANAGE_INDEX_PATHNAME)
+    }
+  }, [username])return (<div className={styles.container}>
-      <Link to="/">
+      <Link to={pathname}><Space><Title><BlockOutlined />


自定义 Hook 统一加载用户信息

思路:

  • 开发获取 Redux 中用户信息
  • 开发获取 服务端 用户信息,并与 Redux 联动
  • 设计页面加载状态(根据用户信息获取与否进行判断)
    • 有用户信息,则停止加载。没有则进行加载。

useGetUserInfo.tsx

import { useSelector } from 'react-redux'
import { StateType } from '../store'
import { UserStateType } from '../store/userReducer'function useGetUserInfo() {const { username, nickname } = useSelector<StateType>((state: StateType) => state.user) as UserStateTypereturn { username, nickname }
}export default useGetUserInfo

useLoadUserData.ts

import { useEffect, useState } from 'react'
import { useRequest } from 'ahooks'
import { getUserInfoService } from '../services/user'
import { useDispatch } from 'react-redux'
import useGetUserInfo from './useGetUserInfo'
import { loginReducer } from '../store/userReducer'function useLoadUserData() {const [waitingUserData, setWaitingUserData] = useState<boolean>(false)const dispatch = useDispatch()// 加载用户信息const { run } = useRequest(getUserInfoService, {manual: true,onSuccess: res => {const { username, nickname } = res// 存储到 Redux 中dispatch(loginReducer({ username, nickname }))},onFinally() {setWaitingUserData(false)},})// Redux 中数据const { username } = useGetUserInfo()useEffect(() => {if (username) {setWaitingUserData(false)}run()}, [username])return { waitingUserData }
}export default useLoadUserData

用户退出功能优化

**思路:**用户退出不仅需要清空 Redux 信息,还要清空本地 token 信息

src/component/userInfo.tsx

 import { LOGIN_PATHNAME } from '../router'import { Button, message } from 'antd'import { UserOutlined } from '@ant-design/icons'
-import { getUserInfoService } from '../services/user'import { removeToken } from '../utils/user-token'
-import { useRequest } from 'ahooks'
+import useGetUserInfo from '../hooks/useGetUserInfo'
+import { useDispatch } from 'react-redux'
+import { logoutReducer } from '../store/userReducer'const UserInfo: FC = () => {const nav = useNavigate()
-  const { data } = useRequest(getUserInfoService)
-  const { username, nickname } = data || {}
+  const { username, nickname } = useGetUserInfo()
+  const dispatch = useDispatch()const logout = () => {
-    removeToken()
+    dispatch(logoutReducer()) // 清空 redux user 中的数据
+    removeToken() // 清空 token 的存储message.success('退出成功')nav(LOGIN_PATHNAME)}


根据用户登录状态动态跳转页面

需求:

  • 当用户已经登陆,在问卷管理页面时,URL中输 /login,会自动返回问卷管理页面,而非再登陆

实现思路:

  • 设计 useNavPage 钩子函数:获取用户状态与URL,根据用户状态判断是否页面跳转走向。

useNavPage.ts

import { useEffect } from 'react'
import { useNavigate, useLocation } from 'react-router-dom'
import {isLoginOrRegister,isNoNeedUserInfo,MANAGE_INDEX_PATHNAME,LOGIN_PATHNAME,
} from '../router'
import useGetUserInfo from './useGetUserInfo'function useNavPage(waitingUserData: boolean) {const { username } = useGetUserInfo()const { pathname } = useLocation()const nav = useNavigate()useEffect(() => {if (waitingUserData) returnif (username) {if (isLoginOrRegister(pathname)) {nav(MANAGE_INDEX_PATHNAME)}return}if (isNoNeedUserInfo(pathname)) {return} else {nav(LOGIN_PATHNAME)}}, [waitingUserData, username, pathname])
}export default useNavPage

src/router/index.ts


export function isLoginOrRegister(pathname: string) {return [LOGIN_PATHNAME, REGISTER_PATHNAME].includes(pathname)
}export function isNoNeedUserInfo(pathname: string) {return [HOME_PATHNAME, LOGIN_PATHNAME, REGISTER_PATHNAME].includes(pathname)
}



Bugfix

Q:请求不断发送

项目中有一处 请求会不断发送,在 Chrome Network 中可以看出。

useLoadUserData.ts

useEffect(() => {if (username) {setWaitingUserData(false)}run() // 这里可能造成循环调用
}, [username])

问题原因:

  • 当Redux中的username为空时,run()会执行获取用户信息
  • 获取成功后通过dispatch(loginReducer)更新username
  • username更新触发useEffect再次执行
  • 形成「获取数据 → 更新username → 触发请求」的循环

解决方案:

修改useLoadUserData.ts中的useEffect:

useEffect(() => {// 当已有用户信息时不再请求if (username) {setWaitingUserData(false)return}run()
}, [username]) // 保持原有依赖


Q:页面刷新自动弹回登陆界面

问题原因分析:

  1. useLoadUserData hook中,用户信息加载完成后才会设置waitingUserData为false
  2. useNavPage hook中会在用户信息未加载完成时判断路由权限
  3. 页面刷新时会清空Redux状态,导致需要重新加载用户信息
  4. 用户信息加载是异步操作,在加载完成前路由守卫已执行跳转判断

解决方案: 修改useLoadUserData.ts文件,在组件挂载时立即触发用户信息加载:

useLoadUserData.ts

function useLoadUserData() {const [waitingUserData, setWaitingUserData] = useState<boolean>(true) // 初始值改为 trueconst dispatch = useDispatch()// 加载用户信息const { run } = useRequest(getUserInfoService, {manual: true,onSuccess: res => {const { username, nickname } = resdispatch(loginReducer({ username, nickname }))},onFinally() {setWaitingUserData(false)},})// 添加 useEffect 立即执行数据加载useEffect(() => {run()}, [])// Redux 中数据const { username } = useGetUserInfo()useEffect(() => {if (username) {setWaitingUserData(false)}}, [username])return { waitingUserData }
}

修改说明:

  1. waitingUserData初始值设为true,确保加载状态初始正确
  2. 添加立即执行的useEffect触发用户信息加载
  3. 保留原有的username依赖检查作为双重保障

同时需要确保在utils/user-token.ts中正确实现了token的持久化存储(根据代码片段推断应已实现)。

这个修改可以保证:

  1. 页面刷新时立即触发用户信息加载
  2. 在用户信息加载完成前保持等待状态
  3. 路由守卫(useNavPage)会等待用户信息加载完成后再进行跳转判断
  4. 避免在异步加载过程中误判未登录状态

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/24660.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMake小结2(PICO为例)

1 前言 之前写过一篇cmake&#xff0c;不过很简单&#xff1a;CMake小结_cmake ${sources}-CSDN博客 构建系统现在真的太多了&#xff0c;完全学不过来的感觉&#xff0c;meson&#xff0c;gardle&#xff0c;buildroot&#xff0c; Maven。。。我是真的有点放弃治疗了。之前…

使用OpenCV实现帧间变化检测:基于轮廓的动态区域标注

在计算机视觉中&#xff0c;帧间差异检测&#xff08;frame differencing&#xff09;是一种常用的技术&#xff0c;用于检测视频流中的动态变化区域。这种方法尤其适用于监控、运动分析、目标追踪等场景。在这篇博客中&#xff0c;我们将通过分析一个基于OpenCV的简单帧间差异…

机器学习01

机器学习的基本过程如下&#xff1a; 1.数据获取 2.数据划分 3.特征提取 4.模型选择与训练 5.模型评估 6.模型调优 一、特征工程&#xff08;重点&#xff09; 0. 特征工程步骤为&#xff1a; 特征提取(如果不是像dataframe那样的数据&#xff0c;要进行特征提取&#…

每日Attention学习24——Strip Convolution Block

模块出处 [TIP 21] [link] CoANet: Connectivity Attention Network for Road Extraction From Satellite Imagery 模块名称 Strip Convolution Block (SCB) 模块作用 多方向条形特征提取 模块结构 模块特点 类PSP设计&#xff0c;采用四个并行分支提取不同维度的信息相比于…

用FileZilla Server 1.9.4给Windows Server 2025搭建FTP服务端

FileZilla Server 是一款免费的开源 FTP 和 FTPS 服务器软件&#xff0c;分为服务器版和客户端版。服务器版原本只支持Windows操作系统&#xff0c;比如笔者曾长期使用过0.9.60版&#xff0c;那时候就只支持Windows操作系统。当时我们生产环境对FTP稳定性要求较高&#xff0c;比…

es-head(es库-谷歌浏览器插件)

1.下载es-head插件压缩包&#xff0c;并解压缩 2.谷歌浏览器添加插件 3.使用

健康检查、k8s探针、Grails+Liquibase框架/health 404 Not Found排查及解决

概述 健康检查对于一个pod而言&#xff0c;其重要性不言而喻。 k8s通过探针来实现健康检查。 探针 k8s提供三种探针&#xff1a; 存活探针&#xff1a;livenessProbe就绪探针&#xff1a;readinessProbe启动探针&#xff1a;startupProbe 存活探针 存活探针决定何时重启…

5个GitHub热点开源项目!!

1.自托管 Moonlight 游戏串流服务&#xff1a;Sunshine 主语言&#xff1a;C&#xff0c;Star&#xff1a;14.4k&#xff0c;周增长&#xff1a;500 这是一个自托管的 Moonlight 游戏串流服务器端项目&#xff0c;支持所有 Moonlight 客户端。用户可以在自己电脑上搭建一个游戏…

【Linux C | 时间】localtime 的介绍、死机、死锁问题以及 localtime_r 函数的时区问题

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

122. 买卖股票的最佳时机 II 反向递推的方法

下面是将你提供的代码整理成一篇Markdown格式的博客内容&#xff1a; 股票买卖的最大利润 问题描述 给定一个整数数组 prices&#xff0c;其中 prices[i] 是股票在第 i 天的价格。你可以选择在某一天买入股票&#xff0c;并在之后的某一天卖出股票。要求计算出你能够获得的最…

详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)

目录 步骤一&#xff1a;首先确认自己是否已经安装JDK步骤二&#xff1a;下载安装Tomcat步骤三&#xff1a;Tomcat配置环境变量步骤四&#xff1a;验证Tomcat配置是否成功步骤五&#xff1a;为IDEA配置Tomcat 步骤一&#xff1a;首先确认自己是否已经安装JDK jdk各版本通用安…

html中的css

css &#xff08;cascading style sheets&#xff0c;串联样式表&#xff0c;也叫层叠样式表&#xff09; css规范一般约定&#xff1a; 1.存放CSS样式文件的目录一般命名为style或css。 2.在项目初期&#xff0c;会把不同类别的样式放于不同的CSS文件&#xff0c;是为了CSS编…

前端项目配置初始化

creat-vue 安装 https://cn.vuejs.org/guide/quick-start.html 官网复制npm安装语句 cmd窗口创建文件夹 npm create vue3.12.2安装webstorm启动vue项目 https://www.jetbrains.com/webstorm/download/other.html 2024.3.2.1 安装依赖 下载包node_modules package 运行服…

Java注解的原理

目录 问题: 作用&#xff1a; 原理&#xff1a; 注解的限制 拓展&#xff1a; 问题: 今天刷面经&#xff0c;发现自己不懂注解的原理&#xff0c;特此记录。 作用&#xff1a; 注解的作用主要是给编译器看的&#xff0c;让它帮忙生成一些代码&#xff0c;或者是帮忙检查…

seacmsv9注入管理员账号密码+orderby+limit

seacmsv9注入管理员账号密码 安装海洋CMS&#xff08;seacms&#xff09; 将upload文件夹里的文件全部上传至网页服务器后&#xff0c;执行以下操作: 请运行http://域名/install/index.php进行程序安装 SQL语句尝试注入 http://127.0.0.1/upload/comment/api/index.php?g…

【构建工具】Gradle Kotlin DSL中的大小写陷阱:BuildConfigField

在Android开发当中&#xff0c;BuildConfig是一个非常有用的功能&#xff0c;它允许我们在构建过程中定义常量&#xff0c;并在运行时使用它们。But&#xff01;&#xff01;当我们从传统的Groovy DSL迁移到Kotlin DSL时或者被Android Studio坑的时候&#xff0c;有一些细微的差…

AI如何改变传统工厂的生产模式?

随着第四次工业革命的浪潮席卷全球&#xff0c;制造业的数字化转型成为企业在竞争中脱颖而出的关键。过去&#xff0c;传统制造业往往依赖于大量的人工操作和低效率的管理流程&#xff0c;而如今&#xff0c;智能化、自动化、数据化已经成为未来制造业的必由之路。从车间到云端…

Redis

redis启动命令 默认端口启动redis&#xff1a; redis-server redis.windows.conf 指定端口9001和9002启动redis(需要新建配置文件&#xff0c;并修改配置文件port属性)&#xff1a; redis-server .\redis-9001.conf redis-server .\redis-9002.conf 检查是否启动Redis &#…

洛谷 P8705:[蓝桥杯 2020 省 B1] 填空题之“试题 E :矩阵” ← 卡特兰数

【题目来源】 https://www.luogu.com.cn/problem/P8705 【题目描述】 把 1∼2020 放在 21010 的矩阵里。要求同一行中右边的比左边大&#xff0c;同一列中下边的比上边的大。一共有多少种方案? 答案很大&#xff0c;你只需要给出方案数除以 2020 的余数即可。 【答案提交】 …

ARM 处理器平台 eMMC Flash 存储磨损测试示例

By Toradex秦海 1). 简介 目前工业嵌入式 ARM 平台最常用的存储器件就是 eMMC Nand Flash 存储&#xff0c;而由于工业设备一般生命周期都比较长&#xff0c;eMMC 存储器件的磨损寿命对于整个设备来说至关重要&#xff0c;因此本文就基于 NXP i.MX8M Mini ARM 处理器平台演示…