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

React使用injectIntl封装高阶组件后报错Cannot call a class as a function

问题原因

报错的核心原因是injectIntl高阶组件的使用位置错误:

  • injectIntl的作用是接收一个React组件,返回一个注入了intl属性的新类组件
  • 你直接将withCheckCountry这个高阶函数(本身不是React组件,是用来生成组件的函数)用injectIntl包裹,导出的就是一个类组件
  • 路由配置中你调用withCheckCountry(CountryApp, availableCountry, loadingCountry)相当于把类组件作为普通函数执行,直接触发Cannot call a class as a function报错
解决方案

方案1:调整injectIntl包裹位置(兼容原有写法)

将injectIntl从包裹外层高阶函数,改为包裹高阶函数返回的内层业务组件,同时从props中获取注入的intl对象,修正后的代码如下:

import React, {useState, useEffect} from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import { toast } from 'react-toastify';
import ToastBody from "components/toastBody/toast";
import { injectIntl } from "react-intl";

const withCheckCountry = (Component, availableCountry, loadingCountry) => {
  // 内层业务组件,从props获取intl
  const InnerComponent = ({intl, ...props}) => {
    if (!loadingCountry) {
      const { countryCode } = props.match.params;
      const isCountryExist = availableCountry.some(
        country => country.countryCode === countryCode.toLocaleUpperCase(),
      );
      const [errorTitle, setErrorTitle] = useState(intl.formatMessage(messages.errorTitle));
      const [countryNotExist, setCountryNotExist] = useState(intl.formatMessage(messages.countryNotExist));

      useEffect(() => {
        setErrorTitle(intl.formatMessage(messages.errorTitle));
        setCountryNotExist(intl.formatMessage(messages.countryNotExist));
      }, [intl]);

      if (!isCountryExist) {
        toast(() => <ToastBody title={errorTitle} message={countryNotExist} />);  
        return <Redirect to="/" />;
      }
    }
    return <Component {...props} />;
  };
  // 仅对内层组件做intl注入
  return injectIntl(InnerComponent);
};

// 修正类型校验:availableCountry是数组不是对象
withCheckCountry.propTypes = {
  availableCountry: PropTypes.array,
};

export default withCheckCountry;

方案2:使用useIntl Hook(更适配函数式组件)

如果项目使用的react-intl版本支持Hook,直接用useIntl可以避免高阶组件嵌套的问题,代码更简洁:

import React, {useState, useEffect} from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import { toast } from 'react-toastify';
import ToastBody from "components/toastBody/toast";
import { useIntl } from "react-intl";

const withCheckCountry = (Component, availableCountry, loadingCountry) => {
  return ({...props}) => {
    // 直接用Hook获取intl对象
    const intl = useIntl();
    if (!loadingCountry) {
      const { countryCode } = props.match.params;
      const isCountryExist = availableCountry.some(
        country => country.countryCode === countryCode.toLocaleUpperCase(),
      );
      const [errorTitle, setErrorTitle] = useState(intl.formatMessage(messages.errorTitle));
      const [countryNotExist, setCountryNotExist] = useState(intl.formatMessage(messages.countryNotExist));

      useEffect(() => {
        setErrorTitle(intl.formatMessage(messages.errorTitle));
        setCountryNotExist(intl.formatMessage(messages.countryNotExist));
      }, [intl]);

      if (!isCountryExist) {
        toast(() => <ToastBody title={errorTitle} message={countryNotExist} />);  
        return <Redirect to="/" />;
      }
    }
    return <Component {...props} />;
  };
};

withCheckCountry.propTypes = {
  availableCountry: PropTypes.array,
};

export default withCheckCountry;

内容的提问来源于stack exchange,提问作者Ala Ben Aicha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:36:04