React useReducer中action对象为undefined问题求助(React Router v6)
问题:React Router v6中通过Context传递dispatch修改状态失败
我正在使用React Router v6,尝试通过Context传递的dispatch函数修改Context中的状态变量,预期流程是:
- 选项值变更 -> 调用dispatch
- reducer读取action值并修改状态变量
- 状态变量通过Context传递给组件使用
但实际出现问题:reducer函数无法获取action对象,读取action时触发"cannot read properties of undefined"错误。
相关代码
main.tsx
const router = createBrowserRouter([ { path: "/", element: <Root />, loader: filmsLoader, children: [ { path: "/", element: <FilmsGrid /> } ] } ]); ReactDOM.createRoot(document.getElementById('root')!).render( <CssBaseline> <Provider> <RouterProvider router={router} /> </Provider> </CssBaseline> );
FilterContext文件
import React, { createContext, useContext, useReducer } from "react"; const FilterContext = createContext('popular'); const FilterReducerContext = createContext(null); function filterReducer({state, action}) { console.log(action.type); // 此处为undefined switch (action) { case "popular": { return { filterState: "popular" }; } case "release-date": { return { filterState: "release-date" }; } default: return state; } } export default function Provider({ children }) { const [filterState, dispatch] = useReducer(filterReducer, 'popular'); return ( <FilterContext.Provider value={filterState}> <FilterReducerContext.Provider value={dispatch}> { children } </FilterReducerContext.Provider> </FilterContext.Provider> ); } export function useFilterContext() { return useContext(FilterContext); } export function useFilterReducer() { return useContext(FilterReducerContext); }
SortType组件
import { Box, FormControl, InputLabel, MenuItem, Select } from "@mui/material"; import { useFilterContext, useFilterReducer } from "../../../FilterContext"; function SortType() { const filterState = useFilterContext(); const dispatch = useFilterReducer(); const changeSortType = (event) => { dispatch({ type: event.target.value }) }; return ( <Box width={'100%'} sx={{ padding: 2 }} > <FormControl fullWidth > <InputLabel id={'sortType-select'} sx={{ "&.MuiInputLabel-root": { left: -12 } }} >Sort by:</InputLabel> <Select labelId="sortType-select" variant="standard" onChange={event => changeSortType(event)} value={filterState} > <MenuItem value={'popular'}>Popular</MenuItem> <MenuItem value={'release-date'}>Release date</MenuItem> </Select> </FormControl> </Box> ); } export default SortType;
问题原因及修复方案
1. Reducer参数写法错误
useReducer的reducer函数接收两个独立参数:当前状态state和动作对象action,而非一个包含两者的对象。你的代码里用了{state, action}解构,导致实际参数不匹配,action被解析为undefined。
2. 状态类型不统一
初始状态是字符串'popular',但reducer返回的是{filterState: "..."}对象,类型不一致会导致后续状态读取异常。
3. Reducer中action判断逻辑错误
你在switch里直接判断action,但dispatch传递的是{type: value}对象,应该判断action.type。
修正后的代码
方案一:保持状态为字符串类型
import React, { createContext, useContext, useReducer } from "react"; const FilterContext = createContext('popular'); const FilterReducerContext = createContext<React.Dispatch<{type: string}>>(null); // 修正reducer参数为独立的state和action function filterReducer(state: string, action: {type: string}) { console.log(action.type); switch (action.type) { case "popular": return "popular"; case "release-date": return "release-date"; default: return state; } } export default function Provider({ children }) { const [filterState, dispatch] = useReducer(filterReducer, 'popular'); return ( <FilterContext.Provider value={filterState}> <FilterReducerContext.Provider value={dispatch}> { children } </FilterReducerContext.Provider> </FilterContext.Provider> ); } export function useFilterContext() { return useContext(FilterContext); } export function useFilterReducer() { return useContext(FilterReducerContext); }
方案二:使用对象存储状态
import React, { createContext, useContext, useReducer } from "react"; // 初始状态改为对象 const FilterContext = createContext({filterState: 'popular'}); const FilterReducerContext = createContext<React.Dispatch<{type: string}>>(null); function filterReducer(state: {filterState: string}, action: {type: string}) { switch (action.type) { case "popular": return {filterState: "popular"}; case "release-date": return {filterState: "release-date"}; default: return state; } } export default function Provider({ children }) { const [filterState, dispatch] = useReducer(filterReducer, {filterState: 'popular'}); return ( <FilterContext.Provider value={filterState}> <FilterReducerContext.Provider value={dispatch}> { children } </FilterReducerContext.Provider> </FilterContext.Provider> ); } export function useFilterContext() { return useContext(FilterContext); } export function useFilterReducer() { return useContext(FilterReducerContext); }
选择方案二时,SortType组件需要调整状态读取方式:
const { filterState } = useFilterContext();
内容的提问来源于stack exchange,提问作者Didi
相关产品推荐
相关产品推荐

