You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Redux+RTKQ Electron应用启动时如何通过持久化令牌获取用户数据?

实现方案

1. 在RTKQ中定义用户详情查询端点

先在你的baseApi中添加获取用户详情的查询端点,利用RTKQ的自动认证头处理逻辑:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { RootState } from '../store';

// 定义用户数据类型
interface User {
  id: string;
  name: string;
  email: string;
  // 补充你的用户字段
}

export const baseApi = createApi({
  reducerPath: 'baseApi',
  baseQuery: fetchBaseQuery({
    baseUrl: '/your-api-base-url',
    prepareHeaders: (headers, { getState }) => {
      // 从已加载的Redux Auth状态中取令牌
      const token = (getState() as RootState).auth.token;
      if (token) {
        headers.set('Authorization', `Bearer ${token}`);
      }
      return headers;
    },
  }),
  endpoints: (builder) => ({
    getUserDetails: builder.query<User, void>({
      query: () => '/user/me',
    }),
  }),
});

// 导出RTKQ自动生成的Hook
export const { useGetUserDetailsQuery } = baseApi;

2. 在根组件中控制加载屏与UI流转

在应用入口组件(比如App.tsx)中,结合Redux状态和RTKQ的查询状态,实现启动屏的显示逻辑:

import { useSelector } from 'react-redux';
import { useGetUserDetailsQuery } from './api/baseApi';
import { RootState } from './store';
import LoadingSplash from './components/LoadingSplash';
import MainApp from './components/MainApp';
import LoginScreen from './components/LoginScreen';

function App() {
  const { token } = useSelector((state: RootState) => state.auth);
  
  // 仅当存在令牌时触发用户详情查询
  const { data: user, isLoading, error } = useGetUserDetailsQuery(undefined, {
    skip: !token, // 无令牌时跳过无效请求
    refetchOnMountOrArgChange: true, // 确保每次启动都拉取最新数据
  });

  // 有令牌且正在加载:显示启动屏
  if (token && isLoading) {
    return <LoadingSplash />;
  }

  // 有令牌但查询失败(比如令牌过期):跳转登录页
  if (token && error) {
    return <LoginScreen />;
  }

  // 获取到用户数据:显示主应用
  if (user) {
    return <MainApp user={user} />;
  }

  // 无令牌:显示登录页
  return <LoginScreen />;
}

export default App;

3. (可选)结合Electron原生启动屏优化体验

如果需要使用Electron原生启动屏而非纯React组件,可以通过IPC通信在用户数据加载完成后再显示主窗口:

主进程(main.ts):

import { app, BrowserWindow, ipcMain } from 'electron';
import path from 'path';

let mainWindow: BrowserWindow | null;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    show: false, // 初始不显示主窗口
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
  });

  mainWindow.loadFile('index.html');

  // 监听渲染进程的加载完成信号
  ipcMain.on('user-data-ready', () => {
    mainWindow?.show(); // 显示主窗口
    // 若使用了Electron原生启动屏模块,可在此关闭:
    // splashScreen.close();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.whenReady().then(createWindow);

渲染进程(App.tsx):

添加useEffect发送IPC信号通知主进程:

import { useEffect } from 'react';
import { ipcRenderer } from 'electron';
// ...其他导入

function App() {
  // ...之前的状态与查询逻辑

  useEffect(() => {
    // 用户数据加载完成后通知主进程
    if (user) {
      ipcRenderer.send('user-data-ready');
    }
  }, [user]);

  // ...渲染逻辑
}

关键注意点

  • 无效请求拦截:通过skip: !token避免无令牌时发起无效API请求
  • 异常处理:令牌存在但查询失败时,及时引导用户重新登录
  • 缓存控制:refetchOnMountOrArgChange: true确保每次启动都获取最新用户数据

内容的提问来源于stack exchange,提问作者Rychu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:35:16