有条件地调用 React Hook “useEffect”。在每个组件渲染中,必须以完全相同的顺序调用 React Hooks

Posted

技术标签:

【中文标题】有条件地调用 React Hook “useEffect”。在每个组件渲染中,必须以完全相同的顺序调用 React Hooks【英文标题】:React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render 【发布时间】:2020-11-27 08:25:16 【问题描述】:
export const FetchDailyData = () => 
  try 

    const [data, setData] = useState( numbers: [], isFetching: false );

    useEffect(() => 
        const fetchData = async () => 
            setData( ...data, isFetching: true );
            const response = await axios.get(`$apiURL/daily`);
            setData(
                ...data,
                numbers: response.data.slice(0, 50),
                isFetching: false
            );
        ;
        fetchData();
    , [data]); 

    console.log(`data= $data.numbers isFetching= $data.isFetching`);

   catch (error) 
    if (error) throw error;
    console.log(error);
    setData( ...data, isFetching: false );
  

谁能帮我解决这个问题?我试图获取 api 数据,但我无法处理这个错误。

【问题讨论】:

为什么要把整个函数体包围在一个 try/catch 中?应该只包装引发错误的最少代码。另外,FetchDailyData 是什么?它不是一个功能组件,它是一个自定义的反应钩子吗?您能否更新问题以包含调用者的代码(即FetchDailyData 的使用位置和方式)? 这能回答你的问题吗? Is it possible to place useEffect inside a if statement? 【参考方案1】:

您不能将useEffect 包装在任何可能导致它无法运行的东西中,包括try/catch。看看你在做什么,这可能是一个更好的选择:

export const FetchDailyData = () => 
    const [data, setData] = useState( numbers: [] );
    const [fetching, setFetching] = useState(false);
    useEffect(() => 
        const fetchData = async () => 
            const response = await axios.get(`$apiURL/daily`);
            setData(
                ...data,
                numbers: response.data.slice(0, 50),
            );
        
        try 
            setFetching(true);
            fetchData();
         catch (error) 
            console.error(error);
         finally 
            setFetching(false);
        
    , [data]); 

【讨论】:

【参考方案2】:

由于您的 useEffect 调用位于 try/catch 内,因此效果可能无法在给定的渲染上运行。它取决于是否有东西抛出。 Hooks 必须在每个渲染中以相同的顺序运行——我认为这与 React 如何在内部跟踪它们有关——并且try/catch 使得该调用可以被跳过。

如果您只是担心 fetch 抛出,请将 try/catch 移动到钩子内,而不是相反。

【讨论】:

以上是关于有条件地调用 React Hook “useEffect”。在每个组件渲染中,必须以完全相同的顺序调用 React Hooks的主要内容,如果未能解决你的问题,请参考以下文章

React useEffect hook load onsnapshot 有条件地反应

我打破了React Hook必须按顺序不能在条件语句中调用的枷锁!

React Hook要点笔记

React Hook要点笔记

react hook 新特性汇总

[react] 使用Hooks要遵守哪些原则?