news 2026/6/24 2:53:35

react中useEffect的用法,以及订阅模式的原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
react中useEffect的用法,以及订阅模式的原理

退出登录的功能示例

import React, { FC, useEffect } from 'react' import { Button, message } from 'antd' import { Link, useNavigate } from 'react-router-dom' import { UserOutlined } from '@ant-design/icons' import { useDispatch } from 'react-redux' // import { useRequest } from 'ahooks' import { LOGIN_PATHNAME } from '../router' // import { getUserInfoService } from '../services/user' import { removeToken } from '../utils/user-token' import useGetUserInfo from '../hooks/useGetUserInfo' import { logoutReducer } from '../store/userReducer' const UserInfo: FC = () => { const nav = useNavigate() const dispatch = useDispatch() // const { data } = useRequest(getUserInfoService) // ajax // const { username, nickname } = data || {} const { username, nickname } = useGetUserInfo() // 从 redux 中获取用户信息 function logout() { dispatch(logoutReducer()) // 清空了 redux user 数据 removeToken() // 清除 token 的存储 message.success('退出成功') } // 监听用户状态变化,如果用户已退出则跳转到登录页 useEffect(() => { if (!username) { nav(LOGIN_PATHNAME) } }, [username, nav]) const UserInfo = ( <> <span style={{ color: '#e8e8e8' }}> <UserOutlined /> {nickname} </span> <Button type="link" onClick={logout}> 退出 </Button> </> ) const Login = <Link to={LOGIN_PATHNAME}>登录</Link> return <div>{username ? UserInfo : Login}</div> } export default UserInfo

用法说明

这个useEffect是用来监听用户登出状态并执行相应跳转的核心逻辑。让我详细解释一下它是如何工作的:

useEffect(() => { if (!username) { nav(LOGIN_PATHNAME) } }, [username, nav])

这段代码的作用是:

  1. 监听依赖项:第二个参数[username, nav]表示这个 effect 依赖于usernamenav这两个变量
  2. 触发条件:只有当usernamenav的值发生变化时,才会重新执行 effect 中的函数
  3. 执行逻辑
    • 检查 username 是否为空(falsy值)
    • 如果为空,就调用nav(LOGIN_PATHNAME)跳转到登录页面

具体流程

当你点击"退出"按钮时:

  1. 触发 logout 函数
  2. logout 函数中执行dispatch(logoutReducer())
  3. logoutReducer 会把 Redux store 中的用户信息重置为初始状态{ username: '', nickname: '' }
  4. 由于 useGetUserInfo() hook 会订阅 Redux store 中的用户信息,所以 username 变量会从实际用户名变为 ' '
  5. useEffect检测到 username 发生了变化,于是重新执行其中的函数
  6. 此时!username为 true(因为 username 是空字符串),所以执行nav(LOGIN_PATHNAME)
  7. 页面跳转到登录页/login

订阅模式介绍

在 React 和 Redux 中,"订阅"是一种设计模式,用于监听状态变化并在状态更新时自动通知相关组件。让我详细解释一下这个过程:
Redux 订阅机制的工作原理
Redux 使用发布-订阅(Publish-Subscribe)模式来实现状态变化的通知机制。下面是具体的工作流程:
1. 订阅建立:当组件使用 useGetUserInfo() 这样的自定义 hook 时,它内部会使用 react-redux 提供的 useSelector hook 来订阅 Redux store 中的特定状态。
2. 状态变化检测:每当 dispatch 一个 action(例如 logoutReducer())时,Redux 会更新 store 中的状态。
3. 通知机制:Redux 会比较更新前后的状态,如果发现有变化,就会通知所有订阅了这部分状态的组件。
4. 组件重新渲染:接收到通知的组件会使用新的状态值重新渲染。

具体到我们的例子

// useGetUserInfo hook 内部大概是这样的 export default function useGetUserInfo() { const { username, nickname } = useSelector<StateType>(state => state.user) return { username, nickname } } // 在 UserInfo 组件中 const { username, nickname } = useGetUserInfo()

当执行dispatch(logoutReducer())时:

  1. Redux store 中的 user 状态从{ username: 'actual_username', nickname: 'actual_nickname' }变成了{ username: '', nickname: '' }
  2. Redux 检测到这个变化
  3. 所有使用 useSelector 订阅了state.user的组件都会收到通知
  4. UserInfo 组件重新渲染,此时 username 变量的值变成了 ' '

useEffect 如何响应变化

useEffect(() => { if (!username) { nav(LOGIN_PATHNAME) } }, [username, nav])

这里的 [username, nav] 是依赖数组,告诉 React:"当 username 或 nav 变化时,请重新执行这个 effect"。
所以整个流程是:
1. 用户点击退出按钮
2. dispatch logoutReducer() 清空用户信息
3. Redux 通知订阅了用户信息的所有组件
4. UserInfo 组件重新渲染,username 更新为空字符串
5. useEffect 检测到 username 变化,执行回调函数
6. 因为 !username 为 true,执行跳转到登录页
这就是所谓的"订阅模式"——组件订阅了状态的一部分,当这部分状态变化时,组件会自动得到通知并做出响应。这是一种非常高效且常用的 React 状态管理模式。

Effect的概念

Effect 是 React 中的一个核心概念,指的是在组件渲染之外执行的操作。这些操作通常包括:

  1. 数据获取(API 请求)
  2. 订阅(如 WebSocket 连接)
  3. 手动修改 DOM
  4. 定时器(setTimeout, setInterval)
  5. 日志记录
  6. 页面跳转(路由导航)

在传统的 Class 组件中,这些操作通常在 componentDidMount、componentDidUpdate 和 componentWillUnmount 等生命周期方法中处理。

useEffect Hook

React Hooks 引入了 useEffect 来统一处理这些副作用。它的基本语法是:

useEffect(() => { // 副作用代码 // 可选的清理函数 return () => { // 清理代码 }; }, [/* 依赖数组 */]);

这里的 effect 做的事情是:

  1. 副作用操作:页面跳转 (nav(LOGIN_PATHNAME))
  2. 触发条件:当 username 变为空时
  3. 依赖项:username 和 nav

为什么叫"Effect"

之所以叫做"effect",是因为它处理的是"副作用",即不是直接参与渲染过程,但却会产生重要影响的操作。在函数式编程中,纯函数不应该有任何副作用,而 effect 正是用来处理这些不可避免的副作用的机制。

Effect 的工作机制

  1. 初始化:组件首次渲染后,执行 effect 函数(如果提供了依赖数组且为空,则只执行一次)
  2. 依赖更新:当依赖数组中的任何一个值发生变化时,重新执行 effect 函数
  3. 清理:如果 effect 函数返回了一个清理函数,它会在下一次 effect 执行前或者组件卸载时被调用

在我们的例子中:

  • 当用户点击退出按钮,触发 logout
  • logout 清除了 Redux 中的用户信息
  • username 从真实用户名变成空字符串
  • useEffect 检测到 username 变化,执行 effect 函数
  • effect 函数发现!username为真,执行页面跳转

这就是 effect 的完整工作流程:监听特定状态变化,当变化发生时执行相应的副作用操作。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 18:22:50

拒绝无效内卷!2025年网文圈公认好用的【写小说软件】红黑榜大公开

作为一名在网文圈摸爬滚打好几年的“老书虫”兼作者&#xff0c;我太懂那种对着空白文档发呆的痛苦了。 哪怕是到了2025年&#xff0c;很多同行依然在电脑前枯坐一整晚&#xff0c;头发掉了一把&#xff0c;就为了憋出个“黄金三章”。要不就是因为大纲没理顺&#xff0c;写到…

作者头像 李华
网站建设 2026/6/22 22:55:43

Kotaemon法律援助机器人公益项目启动

Kotaemon法律援助机器人公益项目启动 在数字鸿沟依然存在的今天&#xff0c;许多普通人面对劳动纠纷、合同争议或家庭矛盾时&#xff0c;往往因信息不对称、律师资源稀缺而错失维权良机。尤其是在偏远地区&#xff0c;一次法律咨询动辄数百元&#xff0c;成为难以承受的负担。正…

作者头像 李华
网站建设 2026/6/22 23:11:03

沉浸式LED显示屏LED大屏幕生产厂家

沉浸式LED显示屏&#xff1a;引领视觉革命的北京瓴地科技有限公司在数字化浪潮席卷全球的今天&#xff0c;视觉体验已成为信息传递、品牌展示与艺术表达的核心。其中&#xff0c;沉浸式LED显示屏作为构建虚拟与现实交融场景的关键载体&#xff0c;正以前所未有的技术深度与视觉…

作者头像 李华
网站建设 2026/6/23 9:54:14

pg配置国内数据源安装

步骤一&#xff1a;# 备份现有的 yum 源配置文件sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup步骤二&#xff1a;#配置清华源sudo tee /etc/yum.repos.d/CentOS-Base.repo << EOF # CentOS-Base.repo # # The mirror system use…

作者头像 李华
网站建设 2026/6/24 8:24:15

AI知识图谱:一张图看懂AI学习全路径

最近写文章&#xff0c;发现自己有一个习惯&#xff1a; 如果没有一个结构化的知识框架&#xff0c;无论是学习还是写作&#xff0c;我都会非常难受。 这算不算强迫症呢&#xff1f;&#xff08;笑&#xff09; 私以为&#xff0c;知识的价值不仅在于“知道”&#xff0c;更在于…

作者头像 李华