0

我有一个按需加载孩子的树结构,这是我的减速器。我遇到的问题是,当我想从 toggleExpandedProp 调用我的 thunk 操作时,我得到了异常(见下文)。我该怎么办?

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { useDispatch } from 'react-redux';
import axios from 'axios';

const dispatch = useDispatch()

export const getRoot = createAsyncThunk('data/nodes/getRoot', async () => {
    const response = await axios.get('http://localhost:5000/api/nodes/root');
    const data = await response.data;
    return data;
});

export const getChildren = createAsyncThunk('data/nodes/getRoot', async params => {
    const response = await axios.get('http://localhost:5000/api/nodes/' + params.id + '/children');
    const data = await response.data;
    return data;
});

const initialState = {
    data: [],
    loading: 'idle'
};

// Then, handle actions in your reducers:
const nodesSlice = createSlice({
    name: 'nodes',
    initialState,
    reducers: {
        toggleExpandedProp: (state, action) => {
            state.data.forEach(element => {
                if(element.id === action.payload.id) {
                    element.expanded = !element.expanded;
                    dispatch(getChildren(element));
                }
            });
        }
    },
    extraReducers: {
      // Add reducers for additional action types here, and handle loading state as needed
      [getRoot.fulfilled]: (state, action) => {
        state.data = action.payload;
      },
      [getChildren.fulfilled]: (state, action) => {
        state.data.push(action.payload);
      }
    }
  })

export const { toggleExpandedProp } = nodesSlice.actions;

export default nodesSlice.reducer;

发生异常。错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。这可能由于以下原因之一而发生:

  1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 您可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本有关如何调试和修复此问题的提示,请参阅https://reactjs.org/link/invalid-hook-call 。
4

1 回答 1

1
const dispatch = useDispatch()

您只能useDispatch在函数组件内部或另一个钩子内部使用。您不能在这样的文件的顶层使用它。

您不应该dispatch从减速器内部调用。但是可以dispatch从一个 thunk 中执行多个操作。所以你可以toggleExpandedProp变成一个重击动作。

您可能需要重新考虑其中的一些逻辑。在扩展节点时从 API 获取子节点然后在折叠节点时再次获取它们真的有意义吗?

export const toggleExpandedProp = createAsyncThunk(
  "data/nodes/toggleExpandedProp",
  async (params, { dispatch }) => {
    dispatch(getChildren(params));
  }
);

这是一种无用的重击,因为我们实际上并没有返回任何东西。您可以将它与getChildren动作结合起来,还是您也需要单独调用该动作?

const nodesSlice = createSlice({
  name: "nodes",
  initialState,
  reducers: {
  },
  extraReducers: {
    [toggleExpandedProp.pending]: (state, action) => {
      state.data.forEach((element) => {
        if (element.id === action.payload.id) {
          element.expanded = !element.expanded;
        }
      });
    },
    [getRoot.fulfilled]: (state, action) => {
      state.data = action.payload;
    },
    [getChildren.fulfilled]: (state, action) => {
      state.data.push(action.payload);
    }
  }
});
于 2021-04-10T04:40:43.657 回答