reactjs React检测到Hook的顺序发生了变化

ztmd8pv5  于 2023-05-22  发布在  React
关注(0)|答案(3)|浏览(117)

我试图显示一些卡的基础上,我从一个API的用户数据。但这个错误一直显示:`警告:React检测到PlanCard调用的Hooks顺序发生了变化。如果不修复,这将导致bug和错误。有关更多信息,请阅读挂钩规则

上一次渲染下一次渲染

  1. useState
  2. useState
  3. useState
  4. useEffect使用效果
    1.未定义的useContext
    ^^^^^^^
    这是我所有的计划卡文件
const [loading, setLoading] = useState(false),
    [showAlert, setShowAlert] = useState(false);

  let headless = typeof window !== 'undefined' &&
    window.location.search.includes('?headless'),
    platform =
      typeof window !== 'undefined' &&
        window.location.search.includes('platform=')
        ? new URL(window.location.href).searchParams.get('platform')
        : false,
    access_token =
      typeof window !== 'undefined' &&
        window.location.search.includes('access_token=')
        ? new URL(window.location.href).searchParams.get('access_token')
        : false,
    plans = [],
    payment_plan = null,
    plan_id = null,
    modal = null,
    purchased_from = null;

  if (headless && access_token) {
    payment_plan = useFetchData(access_token);
    plan_id = payment_plan.plan_id;
  } else { 
    // ToDo:
  }
  if (typeof plan_id === 'string') {
    plans = getPlanCards(plan_id, payment_plan.current_plan_status.toLowerCase());
    purchased_from = payment_plan.purchased_from;
    modal = getPlanCardsANAAlert(purchased_from);
  }
};

这是我的fetchPlan代码:

import axios from 'axios';

const useFetchData = (access_token) => {
  const [plan, setPlan] = useState({});
  let componentMounted = true;

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get(
          `${process.env.GATSBY_API_URL}user/plan/current_plan_detail?token=${access_token}`
        );
        if (componentMounted) {
          setPlan(response.data);
        }
      } catch (error) {
        console.error(error);
      }
    };
    fetchData();
    return () => {
      componentMounted = false;
    };
  }, []);

  return plan;
};

export default useFetchData;
cygmwpex

cygmwpex1#

在if语句中有一个钩子

if (headless && access_token) {
  payment_plan = useFetchData(access_token);
  plan_id = payment_plan.plan_id;
}

这使得你的钩子在组件的渲染之间不稳定,React使用钩子来确定组件的状态,并跟踪组件在数组中定义的钩子,如果它们在渲染之间不同,这意味着它不能正确地比较状态。看这里。
要解决这个问题,你可以使用类似这样的东西:

const payment_plan = useFetchData(access_token);
if(headless && payment_plan) {
...
} else {
...
}
67up9zun

67up9zun2#

React文档说:

仅调用顶层钩子

不要在循环、条件或嵌套函数中调用Hooks。相反,在任何早期返回之前,始终在React函数的顶层使用Hooks。通过遵循此规则,可以确保每次呈现组件时以相同的顺序调用Hooks。这就是为什么React能够在多个useState和useEffect调用之间正确地保留Hooks的状态。
你应该为你的钩子使用相同的流,在页面的重新呈现过程中你不能有不同的钩子

vdgimpew

vdgimpew3#

我最近看到这个bug,看起来像下面这样:
警告:React检测到DashboardSidebar调用的Hooks顺序发生了变化。如果不修复,这将导致bug和错误。
| 上一次渲染|下一次渲染|
| --------------|--------------|
| useContext| useContext|
| useContext| useContext|
| useContext| useContext|
| useDebugValue| useDebugValue|
| useState| useState|
| useEffect| useEffect|
| undefined| useContext|

场景:

DashboardSidebar组件中,我有两个用于侧边导航栏的子组件,它们有条件地相互替换。在其中一个组件中,我使用了以下代码,因此我得到了这个错误:

const settingsContext = useCompanySettingProvider();

// INFO: here I was accessing the value from a useContext hook

说明:

第一个子组件:包括settingsContext。第二个子组件:不包括settingsContext
当我刷新第二个子组件时,settingsContext和第一个子组件一起被删除了。当我试图进入第一个组件(带有settingsContext)被渲染的场景时,抛出了这个错误。
主要原因是现在useContext出现在下一个渲染中,而不是出现在前一个渲染中,这违反了钩子的规则。

解决方案:

我只是将settingsContext移动到父组件中,在渲染之间不会更改settingsContext调用。

请让我知道,如果你有任何疑问或反馈这个答案。

相关问题