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

React Context报错:notifContext.dispatch不是函数问题排查

解决React Context中dispatch未定义的问题

问题根源

  1. 自定义Context未暴露dispatch:在context.js的Provider value中,只传递了state和绑定后的actions,没有把useReducer返回的dispatch包含进去,导致组件中无法获取到dispatch方法。
  2. useContext使用错误:组件中用数组解构const [notifContext] = useContext(NotifContext)获取上下文,而useContext实际返回的是对象,这种写法会导致拿到的notifContext是undefined(对象解构数组会取索引0的值,而上下文对象不是数组)。

解决方案

1. 修改context.js,暴露dispatch

在Provider的value中添加dispatch属性:

import React, {useReducer} from 'react';

export default (reducer, actions, defaultValue) => {
  const Context = React.createContext();

  const Provider = ({children}) => {
    const [state, dispatch] = useReducer(reducer, defaultValue);

    const boundActions = {};
    for (let key in actions) {
      boundActions[key] = actions[key](dispatch);
    }

    return (
      <Context.Provider
        value={{
          state,
          dispatch, // 新增:将dispatch暴露到上下文中
          ...boundActions,
        }}>
        {children}
      </Context.Provider>
    );
  };
  return {Context, Provider};
};

2. 修正组件中useContext的用法

去掉数组解构,直接获取上下文对象(或按需解构属性):

import {Context as NotifContext} from '../../context/NotifContext';

// 错误写法:const [notifContext] = useContext(NotifContext);
const notifContext = useContext(NotifContext); // 正确写法

useEffect(() => {
  if (notifContext?.state?.errorMessage) {
    setToast(
      Toast.show(notifContext?.state?.errorMessage, {
        duration: Toast.durations.SHORT,
        position: Toast.positions.CENTER,
        onHidden: () => notifContext?.dispatch({type: 'clear_error_message'}),
      }),
    );
  } else if (toast) {
    Toast.hide(toast);
  }
}, [notifContext?.state?.errorMessage]);

优化建议(可选)

为了保持Context的封装性,建议在notifContext.js中封装action方法,避免组件直接调用dispatch:

修改notifContext.js:

const defaultValue = {
  errorMessage: '',
  notifCount: [0],
  notifications: [],
};

const notifReducer = (state, action) => {
  switch (action.type) {
    case 'error_1':
      return {
        ...state,
        errorMessage: action.payload,
      };
    case 'clear_error_message':
      return {
        ...state,
        errorMessage: '',
      };
    default:
      return state; // 新增default分支,避免无匹配action时返回undefined
  }
};

// 封装action creators
const actions = {
  clearErrorMessage: (dispatch) => () => {
    dispatch({type: 'clear_error_message'});
  },
  // 其他业务action...
};

export const {Provider, Context} = context(
  notifReducer,
  actions,
  defaultValue,
);

组件中直接调用封装好的方法:

import {Context as NotifContext} from '../../context/NotifContext';

const { state, clearErrorMessage } = useContext(NotifContext);

useEffect(() => {
  if (state?.errorMessage) {
    setToast(
      Toast.show(state.errorMessage, {
        duration: Toast.durations.SHORT,
        position: Toast.positions.CENTER,
        onHidden: clearErrorMessage, // 直接调用封装好的方法
      }),
    );
  } else if (toast) {
    Toast.hide(toast);
  }
}, [state?.errorMessage]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:51:36