Redux:从 slice reducer 操作调用 thunk 操作
Redux: Call thunk action from slice reducer action
我有一个按需加载子项的树结构,这是我的减速器。我遇到的问题是,当我想从 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;
发生异常。
错误:无效挂钩调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一造成的:
- 您的 React 和渲染器版本可能不匹配(例如 React DOM)
- 您可能违反了 Hooks 规则
- 您可能在同一个应用程序中拥有多个 React 副本
有关如何调试和修复此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call。
const dispatch = useDispatch()
您只能在函数组件内部或另一个挂钩内部使用 useDispatch
。您不能像这样在文件的顶层使用它。
你不应该从 reducer 内部调用 dispatch
。但是 dispatch
一个 thunk 的多个动作是可以的。所以你可以把 toggleExpandedProp
变成一个 thunk 动作。
您可能需要重新考虑其中的一些逻辑。在扩展节点时从 API 中获取子节点然后在折叠节点时再次获取它们真的有意义吗?
export const toggleExpandedProp = createAsyncThunk(
"data/nodes/toggleExpandedProp",
async (params, { dispatch }) => {
dispatch(getChildren(params));
}
);
这是一个无用的 thunk,因为我们实际上 return 什么都没有。您可以将它与 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);
}
}
});
我有一个按需加载子项的树结构,这是我的减速器。我遇到的问题是,当我想从 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;
发生异常。 错误:无效挂钩调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一造成的:
- 您的 React 和渲染器版本可能不匹配(例如 React DOM)
- 您可能违反了 Hooks 规则
- 您可能在同一个应用程序中拥有多个 React 副本 有关如何调试和修复此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call。
const dispatch = useDispatch()
您只能在函数组件内部或另一个挂钩内部使用 useDispatch
。您不能像这样在文件的顶层使用它。
你不应该从 reducer 内部调用 dispatch
。但是 dispatch
一个 thunk 的多个动作是可以的。所以你可以把 toggleExpandedProp
变成一个 thunk 动作。
您可能需要重新考虑其中的一些逻辑。在扩展节点时从 API 中获取子节点然后在折叠节点时再次获取它们真的有意义吗?
export const toggleExpandedProp = createAsyncThunk(
"data/nodes/toggleExpandedProp",
async (params, { dispatch }) => {
dispatch(getChildren(params));
}
);
这是一个无用的 thunk,因为我们实际上 return 什么都没有。您可以将它与 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);
}
}
});