如何使用 Redux Toolkit 和 Apollo 的 useQuery 数据设置 initialState?

How to set initialState using Redux Toolkit with data using Apollo's useQuery?

提问人:jonteal 提问时间:11/8/2023 更新时间:11/8/2023 访问量:34

问:

我正在尝试在 redux 工具包切片中调用 useQuery 钩子(功能组件之外不允许的东西)。这是否可行,也许使用 createAsyncThunk 或类似方法?我的应用程序是使用 MERN 堆栈构建的,所以我的数据库是 MongoDB,我使用 Graphql 来获取数据。(在此示例中,我忽略了 reducer,因为我只专注于获取数据并将其设置为初始状态。

import { useQuery } from "@apollo/client";
import { createSlice } from "@reduxjs/toolkit";
import { GET_USER_SETTINGS } from "../graphql/queries/settingsQueries";

const { loading, error, data } = useQuery(GET_USER_SETTINGS);

const { gridView } = data.settings;

const initialState = {
   gridView,
};

const settingsSlice = createSlice({
  name: "settings",
  initialState,
  reducers: {
    setGridViewOff(state) {
      state.gridView = false;
    },
    setGridViewOn(state) {
      state.gridView = true;
    }, 
},
});

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

export default settingsSlice.reducer;
reactjs mongodb graphql redux-toolkit apollo-client

评论


答:

0赞 Drew Reese 11/8/2023 #1

你是对的,你不能从 Redux slice 代码调用。我在这里的建议是使用一些“未定义”的初始状态,并使用钩子来“初始化”值。useQuerygridViewuseEffectgridView

类似于以下示例的内容:Something similar to the following example:

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

const initialState = {
   gridView: undefined,
};

const settingsSlice = createSlice({
  name: "settings",
  initialState,
  reducers: {
    initializeGridView: (state, action) => {
      state.gridView = action.payload;
    },
    setGridViewOff(state) {
      state.gridView = false;
    },
    setGridViewOn(state) {
      state.gridView = true;
    }, 
  },
});

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

export default settingsSlice.reducer;
import { useEffect } from "react";
import { useQuery } from "@apollo/client";
import { useDispatch } from "react-redux";
import { initializeGridView } from "../path/to/settings.slice";
import { GET_USER_SETTINGS } from "../graphql/queries/settingsQueries";

const useInitializeGridView = () => {
  const dispatch = useDispatch();
  const { loading, data } = useQuery(GET_USER_SETTINGS);

  useEffect(() => {
    if (!loading) {
      const gridView = !!data?.settings?.gridView;
      dispatch(initializeGridView(gridView));
    }
  }, [loading, data]);
};

在应用程序中靠近 Redux 所在范围的根附近的某个位置调用,例如在 ReactTree 的 Redux 组件下。任何依赖于该值的 UI 都应首先检查是否定义了该值,然后使用定义的 true/false 值。useInitializeGridViewProviderstate.settings.gridView

-1赞 BugHunter 11/8/2023 #2

您可以通过创建一个 Redux Thunk 操作来获取数据并设置初始状态,然后从您的组件调度 Redux Thunk 操作来处理这个问题。

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

export const fetchUserSettings = createAsyncThunk("settings/fetchUserSettings", async (_, { dispatch }) => {
  try {
    const { data } = await useQuery(GET_USER_SETTINGS);
    const gridView = data.settings.gridView;

    return { gridView };
  } catch (error) {
    throw error;
  }
});

const initialState = {
  gridView: null,
};

const settingsSlice = createSlice({
  name: "settings",
  initialState,
  reducers: {
    setGridViewOff(state) {
      state.gridView = false;
    },
    setGridViewOn(state) {
      state.gridView = true;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(fetchUserSettings.fulfilled, (state, action) => {
      state.gridView = action.payload.gridView;
    });
  },
});

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

export default settingsSlice.reducer;