0

0

React-Redux 应用中实现用户数据的条件加载

DDD

DDD

发布时间:2025-10-22 12:06:30

|

346人浏览过

|

来源于php中文网

原创

React-Redux 应用中实现用户数据的条件加载

本教程旨在解决 react-redux 应用中未登录用户不必要地请求用户数据和敏感 api key 导致 401 错误的问题。我们将通过在 redux thunk 中引入认证状态检查机制,并结合组件层面的状态判断,实现用户数据的按需加载,从而优化应用性能并提升用户体验。

在构建基于 React 和 Redux 的认证应用时,一个常见的挑战是如何确保只有在用户登录后才尝试加载其专属数据或需要认证的敏感资源。如果应用在初始化时无条件地发起这些请求,未登录用户将会收到大量的 401 Unauthorized 错误,这不仅会污染开发者工具的控制台,还会造成不必要的网络请求,影响应用性能。

问题根源分析

根据提供的代码示例,问题主要来源于 App.js 中的 useEffect 钩子:

  1. store.dispatch(loadUser()):在应用启动时无条件地分发 loadUser action。
  2. axios.get('/api/stripeapikey'):同样在应用启动时无条件地请求 Stripe API Key。

loadUser action 内部通过 axios.get('/api/profile') 尝试获取用户资料。如果用户当前没有有效的认证会话(例如,尚未登录或认证 token 已过期),后端 API 会拒绝这些请求并返回 401 状态码,从而导致前端出现错误。

解决方案:基于认证状态的条件加载

为了解决这个问题,核心思想是在发起这些需要认证的请求之前,先检查用户的认证状态。我们可以通过以下两种主要方式实现:

  1. 在 Redux Thunk 内部检查: 在 loadUser action creator 中,利用 Redux Thunk 提供的 getState 函数访问当前 Redux 状态,判断用户是否已认证。这种方法将认证检查逻辑封装在 action 内部,使得 loadUser 无论从何处调用都能保持一致的按需加载行为。
  2. 在组件中检查: 在 App.js 的 useEffect 中,使用 useSelector 获取认证状态,然后有条件地 dispatch loadUser 或请求 Stripe API Key。

本教程将结合这两种方法:loadUser 动作在 Thunk 内部进行认证检查,而 Stripe API Key 的请求则在 App.js 中基于 Redux 状态进行判断。

极限网络办公Office Automation
极限网络办公Office Automation

专为中小型企业定制的网络办公软件,富有竞争力的十大特性: 1、独创 web服务器、数据库和应用程序全部自动傻瓜安装,建立企业信息中枢 只需3分钟。 2、客户机无需安装专用软件,使用浏览器即可实现全球办公。 3、集成Internet邮件管理组件,提供web方式的远程邮件服务。 4、集成语音会议组件,节省长途话费开支。 5、集成手机短信组件,重要信息可直接发送到员工手机。 6、集成网络硬

下载

实现用户数据的条件加载

首先,我们需要修改 loadUser Redux Thunk,引入 getState 参数来访问 Redux store 的当前状态。在发起 API 请求之前,检查 getState().auth.isAuthenticated(假设 auth reducer 中有一个 isAuthenticated 字段表示用户是否登录)。

// actions/user.js
import axios from 'axios';

export const loadUser = () => async (dispatch, getState) => {
    // 在尝试加载用户之前,检查用户是否已认证
    // 假设 Redux 状态中有一个 auth.isAuthenticated 字段
    if (!getState().auth.isAuthenticated) {
        // 如果用户未认证,则直接返回,不执行后续的 API 请求
        // 这样可以避免在未登录状态下发起不必要的 /api/profile 请求
        return;
    }

    try {
        dispatch({ type: 'LOAD_USER_REQ' });

        // 注意:根据您的代理配置,API 路径可能是 '/api/profile'
        const { data } = await axios.get('/api/profile'); 

        dispatch({
            type: 'LOAD_USER_SUCCESS',
            payload: data.user
        });

    } catch (error) {
        // 即使进行了预检查,API 请求仍可能因其他原因失败(如 token 过期),
        // 此时应处理错误,并将认证状态设为 false。
        dispatch({
            type: 'LOAD_USER_FAIL',
            payload: error.response && error.response.data.message
                ? error.response.data.message
                : error.message
        });
    }
};

export const clearErrors = () => async dispatch => {
    dispatch({ type: 'CLEAR_ERRORS' });
};

对应的 Reducer 状态管理:

为了使上述检查生效,authReducer 必须正确地管理 isAuthenticated 状态。isAuthenticated 应该在用户成功登录/注册后设为 true,在登出或加载用户失败时设为 false。

// reducers/user.js
const initialState = {
    user: null, // 初始用户数据设为 null
    isAuthenticated: false, // 初始认证状态为 false
    loading: false,
    error: null
};

export const authReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'LOAD_USER_REQ':
            return {
                ...state,
                loading: true,
                error: null
            };

        case 'LOAD_USER_SUCCESS':
            return {
                ...state,
                loading: false,
                isAuthenticated: true,
                user: action.payload,
                error: null
            };

        case 'LOAD_USER_FAIL':
            return {
                ...state,
                loading: false,
                isAuthenticated: false, // 加载失败,视为未认证
                user: null, // 清空用户数据
                error: action.payload
            };

        // 假设您有登录/注册/登出相关的 action
        // case 'LOGIN_SUCCESS':
        // case 'REGISTER_SUCCESS':
        //     return { ...state, loading: false, isAuthenticated: true, user: action.payload, error: null };
        // case 'LOGOUT_SUCCESS':
        //     return { ...state, loading: false, isAuthenticated: false, user: null, error: null };

        case 'CLEAR_ERRORS':
            return {
                ...state,
                error: null
            };

        default:
            return state;
    }
};

实现 Stripe API Key 的条件加载

对于 Stripe API Key,由于它在 App.js 的 useEffect 中直接通过 axios 请求,我们可以利用 useSelector 从 Redux store 中获取认证状态,然后有条件地执行请求。

// App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import axios from 'axios';
import { useSelector } from 'react-redux'; // 导入 useSelector

import Header from './components/Header';
import Home from './components/Home';
import Payment from './components/Payment';
import Profile from './components/Profile';

import { loadUser } from './actions/user';
import store from './store';

export default function App() {
    const [stripeApiKey, setStripeApiKey] = useState('');
    // 从 Redux store 中获取认证状态
    const { isAuthenticated } = useSelector(state => state.auth); 

    useEffect(() => {
        // 无论用户是否认证,都尝试 dispatch loadUser。
        // loadUser thunk 内部会根据 isAuthenticated 状态决定是否发起 API 请求。
        store.dispatch(loadUser());

        // 只有当用户已认证时才请求 Stripe API Key
        if (isAuthenticated) {
            (async () => {
                try {
                    const { data } = await axios.get('/api/stripeapikey');
                    setStripeApiKey(data.stripeApiKey);
                } catch (error) {
                    console.error('Failed to load Stripe API Key:', error);
                    // 可以在此添加错误处理,例如 dispatch 一个 action 来更新 Redux 状态
                }
            })();
        } else {
            // 如果用户未认证,确保清空或重置 stripeApiKey
            setStripeApiKey('');
        }

    }, [isAuthenticated]); // 依赖 isAuthenticated,当认证状态改变时重新运行此 effect

    return (
        
            
} /> {/* 这些路由可能需要额外的路由保护

相关专题

更多
登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6106

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

812

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1064

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

1277

2024.03.01

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

510

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

278

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5293

2023.08.17

菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

0

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号