【问题标题】:React HOC Using useEffect()使用 useEffect() 反应 HOC
【发布时间】:2021-05-11 05:44:47
【问题描述】:

所以我使用 HOC 进行一般错误处理,反应如下:

import React, { useState, useEffect } from 'react'
import Modal from '../../UI/Modal/Modal'
const WithErrorHandler = (WrappedComponent, axios) => {
    const NewComponent = props => {
        console.log('UseState')
        const [error, setError] = useState(null)
        console.log('runs')
        useEffect(() => {
            const req = axios.interceptors.request.use(config => {
                console.log('request intercepted')
                return config
            })
            const res = axios.interceptors.response.use(null, error => {
                setError(error)
                return Promise.reject(error)
            })
            
            return () => {
                axios.interceptors.request.eject(req)
                axios.interceptors.response.eject(res)
            }
        }, [])
        return (
            <div>
                {console.log('render')}
                {error ? (
                    <Modal clickHandler={() => setError(null)}> {error.message}</Modal>
                ) : null}
                <WrappedComponent {...props} />
            </div>
        )
    }
    return NewComponent
}
export default WithErrorHandler

我遇到的问题是我有一个组件在它的 useEffect() 中触发 axios 请求。 当我尝试用我的 WithErrorHandler 包装这个组件时,包装组件的 useEffect 首先触发,然后 HOC withErrorHandler 的 useEffect 运行。这会导致 axios 请求比 HOC 注册 axios 拦截器的速度更快。任何有关如何解决此问题的想法都将不胜感激。

【问题讨论】:

    标签: reactjs axios use-effect


    【解决方案1】:

    您可以定义一个中间状态来阻止渲染包装的组件。

    const WithErrorHandler = (WrappedComponent, axios) => {
      const NewComponent = (props) => {
            
        const [ready, setReady] = useState(false); // HERE
    
        console.log("UseState");
        const [error, setError] = useState(null);
        console.log("runs");
        useEffect(() => {
          const req = axios.interceptors.request.use((config) => {
            console.log("request intercepted");
            return config;
          });
          const res = axios.interceptors.response.use(null, (error) => {
            setError(error);
            return Promise.reject(error);
          });
    
          setReady(true); // HERE
    
          return () => {
            axios.interceptors.request.eject(req);
            axios.interceptors.response.eject(res);
          };
        }, []);
    
        if (!ready) return null; // HERE
    
        return (
          <div>
            {console.log("render")}
            {error ? (
              <Modal clickHandler={() => setError(null)}> {error.message}</Modal>
            ) : null}
            <WrappedComponent {...props} />
          </div>
        );
      };
      return NewComponent;
    };
    

    它的作用是确保 axios 拦截器已初始化,并且可以很好地渲染包装的组件。

    您可以从 HOC 返回更合理的状态,而不是 if (!ready) return null;,例如 if (!ready) return &lt;p&gt;Initializing...&lt;/p&gt;

    【讨论】:

      【解决方案2】:

      您需要一个额外的渲染来运行NewComponent 回调,在WrappedComponent 上添加一个条件渲染应该可以解决问题。

      请注意,我们将 isFirstRender 设置为承诺成功,请根据您的用例进行更改。

      const WithErrorHandler = (WrappedComponent, axios) => {
        const NewComponent = (props) => {
          const [isFirstRender, setIsFirstRender] = useState(true);
          const [error, setError] = useState(null);
      
          useEffect(() => {
            if (isFirstRender) {
              const req = axios.interceptors.request.use((config) => {
                return config;
              });
      
              // Check req success
              if (req.isSuccess) { setIsFirstRender(false); }
      
              const res = axios.interceptors.response.use(null, (error) => {
                setError(error);
                return Promise.reject(error);
              });
      
              return () => {
                axios.interceptors.request.eject(req);
                axios.interceptors.response.eject(res);
              };
            }
          }, [isFirstRender]);
      
          return (
            <div>
              {error ? (
                <Modal clickHandler={() => setError(null)}> {error.message}</Modal>
              ) : null}
              {!isFirstRender && <WrappedComponent {...props} />}
            </div>
          );
        };
        return NewComponent;
      };
      

      【讨论】:

        猜你喜欢
        • 2020-05-07
        • 2021-10-03
        • 2018-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-25
        • 1970-01-01
        • 2020-07-08
        相关资源
        最近更新 更多