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

React类组件HOC正常运行,Hook函数式HOC失效,求问题排查

Fixing Your Hook-Based Error Handler HOC

Hey there! Let's break down why your function-based HOC isn't working as expected, and fix it step by step.

The Core Problem: Duplicate Axios Interceptors

In your class component version, you set up interceptors once in componentWillMount (which runs only when the component mounts). But in the Hook version, you're creating interceptors directly in the component function body—this means every time the component re-renders, you're adding a new pair of request/response interceptors to your axios instance.

Over time, this builds up duplicate interceptors: each one tries to update the error state, leading to inconsistent behavior (like errors not clearing properly, or multiple modals popping up). Plus, the cleanup logic in your useEffect won't catch all these duplicate interceptors, causing memory leaks.

Additional Small Issues

  • You weren't passing the error prop to the Modal component (like you did in the class version), which might break any logic inside the Modal that relies on it.
  • In the response interceptor, you were setting error to the full err object instead of err.response—mismatching the class component's behavior.

Fixed Hook-Based HOC

Here's the corrected code, with explanations:

import React, { useState, useEffect } from "react";
import Modal from "../components/UI/Modal/Modal";

const withErrorHandler = (WrappedComponent, axios) => {
  return (props) => {
    const [error, setError] = useState(null);

    // Set up interceptors ONCE when the component mounts
    useEffect(() => {
      const requestInterceptor = axios.interceptors.request.use((req) => {
        setError(null);
        return req;
      });

      const responseInterceptor = axios.interceptors.response.use(
        (res) => res,
        (err) => {
          // Match class component behavior: store the response error
          setError(err.response);
        }
      );

      // Cleanup: Remove interceptors when the component unmounts
      return () => {
        axios.interceptors.request.eject(requestInterceptor);
        axios.interceptors.response.eject(responseInterceptor);
      };
    }, [axios]); // Depend on axios to reset interceptors if the instance changes

    const errorConfirmedHandler = () => {
      setError(null);
    };

    return (
      <React.Fragment>
        <Modal 
          showModal={!!error} 
          error={error} // Restore the error prop for Modal
          closeModal={errorConfirmedHandler}
        >
          {error ? error.message : null}
        </Modal>
        <WrappedComponent {...props} />
      </React.Fragment>
    );
  };
};

export default withErrorHandler;

Key Fixes Explained

  1. Interceptor Setup in useEffect: By wrapping the interceptor creation in useEffect with a dependency array containing axios, we ensure interceptors are only created once when the component mounts (or if the axios instance changes). This prevents duplicate interceptors from piling up.
  2. Proper Cleanup: The cleanup function inside useEffect runs when the component unmounts, removing the interceptors just like componentWillUnmount did in the class version—no more memory leaks.
  3. Matching Error Handling: We now set error to err.response (same as the class component) and pass the error prop to Modal, ensuring consistent behavior across both versions.
  4. Simplified showModal: Using !!error is a cleaner way to convert the error state to a boolean, instead of the ternary check.

This should make your Hook-based HOC work exactly like the class component version!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:12:33