这是避免“您是否在提前返回后不小心调用了 React Hook?"的安全方法吗? [英] Is this a safe way to avoid "Did you accidentally call a React Hook after an early return?"

查看:65
本文介绍了这是避免“您是否在提前返回后不小心调用了 React Hook?"的安全方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个这样的函数组件:

I wrote a function component like this:

export const SiteMap: React.FunctionComponent = () => {

  return useGetSetData<I.SiteMap>({
    title: "Site Map",
    getData: () => IO.getSiteMap(),
    showData: Page.SiteMap
  });
}

效果很好.

顺便说一下,我的 useGetSetData 是一个高阶组件"函数,它使用 useStateuseEffect 来获取数据,并且然后将该数据(在获取之后)传递给要显示的传入表示组件.其参数为:

By the way, my useGetSetData is a "high order component" function, which uses useState and useEffect to fetch data, and which then passes that data (after it's fetched) to the passed-in presentation component to be shown. Its parameters are:

interface UseGetDataPropsT<T> {
  title: string,
  getData: () => Promise<T>,
  showData: (data: T) => ReactElement
}

无论如何,下次我尝试使用一个页面时,该页面的内容取决于 URL 中的其他一些内容,我将其编码如下:

Anyway, the next time I try this is with a page, whose content depends on some other things in the URL, which I code like this:

type RouterProps = ReactRouter.RouteComponentProps<any>;

export const Image: React.FunctionComponent<RouterProps> = (props: RouterProps) => {

  const imageId: number | undefined = getId(props, "Image");
  if (!imageId) {
    return NoMatch(props);

  return useGetSetData<I.Image>({
    title: "Image",
    getData: () => IO.getImage(imageId),
    showData: Page.Image
  });
}

这会产生一条错误消息:

This produces an error message:

有条件地调用 React Hook "useGetSetData".在每个组件渲染中,必须以完全相同的顺序调用 React Hooks.您是否在提前返回后不小心调用了 React Hook?反应钩子/钩子规则

React Hook "useGetSetData" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks

如果我按如下方式重新编码,那么它可以工作:

If I recode that as follows then it works:

export const Image: React.FunctionComponent<RouterProps> = (props: RouterProps) => {

  const imageId: number | undefined = getId(props, "Image");
  if (!imageId) {
    return NoMatch(props);

  return ImageId(imageId);
}

export const ImageId: React.FunctionComponent<number> = (imageId: number) => {
  return useGetSetData<I.Image>({
    title: "Image",
    getData: () => IO.getImage(imageId),
    showData: Page.Image
  });
}

这是一个微不足道的变化,即它在功能上与我之前编写的代码相同.

This is a trivial change, i.e. it's functionally equivalent to what I coded before.

它避免了上面的错误信息,而且它似乎可以正确运行.

It avoids the error message above, and it appears to act correctly.

我的问题是:

  • 我的解决方法是否安全,即此代码是否正常?
  • 如果没有,那么在什么情况下它可能会失败

推荐答案

不安全react-hooks/rules-of-hooks 只是一个 eslint 规则 不够聪明(还)意识到你被骗了

not safe, react-hooks/rules-of-hooks is just an eslint rule that is not smart enough (yet) to realize you cheated

问题与之前完全相同,在 https://overreacted.io/why-do-hooks-rely-on-call-order/

解决方案是有条件地渲染一个单独的组件(会无条件地调用钩子)=> 使用 JSX 的 React.createElement(ImageId...) 而不是调用普通函数:

solution would be to conditionally render a separate component (that would call the hook unconditionally) => use React.createElement(ImageId...) of JSX instead of calling a plain function:

  if (!imageId) {
    return <NoMatch {...props} />};
  }

  return <ImageId {...{imageId}} />;

这篇关于这是避免“您是否在提前返回后不小心调用了 React Hook?"的安全方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆