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

如何用Apollo useQuery取数并通过Redux Toolkit设置initialState?

解决方案:在Redux Toolkit中整合GraphQL数据获取

你遇到的核心问题是React Hook(如useQuery)只能在函数组件或自定义Hook内部调用,无法直接在Redux slice这类非Hook/组件的代码块中使用。下面提供两种可行的实现方案,适配你的MERN+GraphQL技术栈:


方案一:用createAsyncThunk结合Apollo Client直接查询

通过Apollo Client的client.query方法(非Hook版本)在异步thunk中执行GraphQL查询,再将结果同步到Redux状态中。

步骤1:导出Apollo Client实例

确保你有一个全局的Apollo Client实例可以导入:

// apolloClient.js
import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: '/graphql', // 你的GraphQL端点地址
  cache: new InMemoryCache(),
});

export default client;

步骤2:修改settings slice,添加异步thunk

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import client from "../apolloClient";
import { GET_USER_SETTINGS } from "../graphql/queries/settingsQueries";

// 创建异步thunk,负责获取用户设置
export const fetchUserSettings = createAsyncThunk(
  'settings/fetchUserSettings',
  async () => {
    const { data } = await client.query({ query: GET_USER_SETTINGS });
    return data.settings;
  }
);

const initialState = {
  gridView: false, // 设置默认值
  loading: false,
  error: null,
};

const settingsSlice = createSlice({
  name: "settings",
  initialState,
  reducers: {
    setGridViewOff(state) {
      state.gridView = false;
    },
    setGridViewOn(state) {
      state.gridView = true;
    }, 
  },
  // 处理异步thunk的状态更新
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserSettings.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchUserSettings.fulfilled, (state, action) => {
        state.loading = false;
        state.gridView = action.payload.gridView;
      })
      .addCase(fetchUserSettings.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

export const { setGridViewOff, setGridViewOn } = settingsSlice.actions;
export default settingsSlice.reducer;

步骤3:在组件中触发异步查询

在应用初始化的组件(如App.js)中调用thunk,触发数据获取:

import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { fetchUserSettings } from './slices/settingsSlice';

function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(fetchUserSettings());
  }, [dispatch]);

  return <div>...</div>;
}

export default App;

方案二:组件内用useQuery,同步结果到Redux

如果组件本身需要使用useQuery的查询结果,可以在组件内完成查询后,通过dispatch将数据存入Redux。

步骤1:在slice中添加同步数据的reducer

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  gridView: false,
};

const settingsSlice = createSlice({
  name: "settings",
  initialState,
  reducers: {
    setGridViewOff(state) {
      state.gridView = false;
    },
    setGridViewOn(state) {
      state.gridView = true;
    },
    // 添加同步用户设置的reducer
    setUserSettings(state, action) {
      state.gridView = action.payload.gridView;
      // 若有其他设置字段,可扩展为:state = { ...state, ...action.payload }
    },
  },
});

export const { setGridViewOff, setGridViewOn, setUserSettings } = settingsSlice.actions;
export default settingsSlice.reducer;

步骤2:在组件中执行查询并同步到Redux

import { useQuery } from "@apollo/client";
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { setUserSettings } from './slices/settingsSlice';
import { GET_USER_SETTINGS } from "../graphql/queries/settingsQueries";

function SettingsComponent() {
  const { loading, error, data } = useQuery(GET_USER_SETTINGS);
  const dispatch = useDispatch();

  // 查询完成后同步到Redux
  useEffect(() => {
    if (data?.settings) {
      dispatch(setUserSettings(data.settings));
    }
  }, [data, dispatch]);

  if (loading) return <p>加载中...</p>;
  if (error) return <p>错误:{error.message}</p>;

  return <div>...</div>;
}

方案选择建议

  • 若希望Redux完全管理数据获取的异步状态(loading/error),优先选择方案一;
  • 若组件本身需要直接使用useQuery的结果,同时需要同步到Redux,选择方案二更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:03:16