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

如何将createApi获取的用户数据存储到Redux Store中?

如何将RTK Query获取的用户数据存入Redux Store?

我想把通过createApi获取的用户数据(姓名、邮箱等)存储到Redux Store的authSlice中,但不清楚具体实现方法和最佳实践。以下是我的代码示例:

userApi.js

export const userApi = createApi({
  reducerPath: "userApi",
  baseQuery: fetchBaseQuery({
    baseUrl: "http://localhost:5000" ,
    credentials: "include",
    tagTypes: ['Users'],
    prepareHeaders: (headers, { getState }) => {
      const { accessToken } = getState().auth;
      if (accessToken) {
        headers.set('Authorization', `Bearer ${accessToken}`);
      }
      return headers;
    }
  }),
  endpoints: (builder) => ({
    getUsers: builder.query({
      query: () => "/users",
      providesTags: ["Users"],
      transformResponse: (response) => response.data,
    }),
    loginUser: builder.mutation({
      query: (value) => ({
        url: "/login",
        method: "POST",
        body: value,
      })
    }),
    // 其他端点...
  })
});

export const { 
  useGetUsersQuery, 
  useLoginUserMutation
} = userApi;

authSlice.js

const initialState = {
  user: null,
  accessToken : null,
}

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    setUser: (state, action) => {
      state.user = action.payload;
    },
    setAccessToken: (state, action) => {
      state.accessToken = action.payload;
    },
    logOut: () => initialState
  },
})

export const { setUser, setAccessToken, logOut } = authSlice.actions;

export default authSlice.reducer

export const selectUser = (state) => state.auth.user;
export const selectAccessToken = (state) => state.auth.accessToken;

我之前了解过可以使用extraReducer和addCase,但不确定这是否是最佳实践。


实现方案与最佳实践

方法一:用extraReducers监听RTK Query异步动作

RTK Query会自动生成对应端点的异步动作类型,你可以在authSlice中通过extraReducers监听这些动作,实现数据自动存入state。

修改后的authSlice代码

import { createSlice } from '@reduxjs/toolkit';
import { userApi } from './userApi'; // 导入userApi

const initialState = {
  user: null,
  accessToken: null,
};

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    setUser: (state, action) => {
      state.user = action.payload;
    },
    setAccessToken: (state, action) => {
      state.accessToken = action.payload;
    },
    logOut: () => initialState,
  },
  extraReducers: (builder) => {
    // 监听getUsers查询成功的动作
    builder.addCase(userApi.endpoints.getUsers.matchFulfilled, (state, action) => {
      // 根据你的接口返回结构调整,这里假设返回的是用户数组,取第一个
      state.user = action.payload[0];
    });

    // 监听loginUser mutation成功的动作
    builder.addCase(userApi.endpoints.loginUser.matchFulfilled, (state, action) => {
      // 假设登录接口返回包含accessToken和user的对象
      state.accessToken = action.payload.accessToken;
      state.user = action.payload.user;
    });

    // 可选:监听请求失败的动作,处理错误场景
    builder.addCase(userApi.endpoints.getUsers.matchRejected, (state) => {
      state.user = null;
    });
  },
});

export const { setUser, setAccessToken, logOut } = authSlice.actions;
export default authSlice.reducer;
export const selectUser = (state) => state.auth.user;
export const selectAccessToken = (state) => state.auth.accessToken;

这种方式的优势是自动化同步,不需要在组件中手动处理,只要请求成功就自动更新全局state,适合认证信息这类需要全局共享的数据。

方法二:组件内手动dispatch动作

如果需要在存储数据前做额外处理(比如数据校验、格式转换),可以在组件中调用RTK Query的hook,拿到数据后手动触发setUser或setAccessToken动作。

组件示例代码

import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { useGetUsersQuery, useLoginUserMutation } from './userApi';
import { setUser, setAccessToken } from './authSlice';

function UserPage() {
  const dispatch = useDispatch();
  // 调用getUsers查询hook
  const { data: users, isSuccess } = useGetUsersQuery();

  // 查询成功后手动存储用户数据
  useEffect(() => {
    if (isSuccess && users?.length > 0) {
      // 这里可以添加数据处理逻辑
      const processedUser = { ...users[0], fullName: `${users[0].firstName} ${users[0].lastName}` };
      dispatch(setUser(processedUser));
    }
  }, [isSuccess, users, dispatch]);

  // 登录逻辑示例
  const [login] = useLoginUserMutation();
  const handleLogin = async (formData) => {
    const result = await login(formData);
    if (result.data) {
      dispatch(setAccessToken(result.data.accessToken));
      dispatch(setUser(result.data.user));
    }
  };

  return (
    <div>
      {/* UI内容 */}
    </div>
  );
}

最佳实践总结

  1. 优先选择extraReducers:对于认证信息这类全局共享的数据,extraReducers能实现自动化同步,减少组件内的重复逻辑,代码更简洁。
  2. 避免冗余存储:如果RTK Query的缓存数据已经能满足UI渲染需求,无需额外存入authSlice——RTK Query本身提供了缓存、自动重取等机制。只有当需要在非组件逻辑(比如中间件、其他slice)中访问这些数据时,才需要存入独立slice。
  3. 匹配接口返回结构:无论哪种方式,都要根据实际接口的返回格式调整action.payload的处理逻辑,确保数据正确存入state。
  4. 处理错误场景:记得监听matchRejected动作,在请求失败时清空或重置相关state,避免脏数据残留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 18:47:20