代码之家  ›  专栏  ›  技术社区  ›  ChrisW

这是一种安全的方法来避免“你在提前返回后意外调用了React Hook吗?”

  •  0
  • ChrisW  · 技术社区  · 7 年前

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

    那很好。

    useGetSetData 是一个“高阶组件”函数,它使用 useState 和 useEffect 获取数据,然后将该数据(在获取数据后)传递给要显示的传入表示组件。 其参数为:

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

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

    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
      });
    }
    

    React钩子“useGetSetData”被有条件地调用。在每个组件渲染中,必须以完全相同的顺序调用React挂钩。你是不是在早归后不小心打电话给了React Hook?反应挂钩/挂钩规则

    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
      });
    }
    

    这是一个微不足道的变化,也就是说,它在功能上等同于我以前编写的代码。

    它避免了上面的错误消息,并且似乎操作正确。


    • 我周围的工作安全吗,也就是说,这个代码可以吗?
    • 如果不是,那么在什么情况下它会失败
    0 回复  |  直到 7 年前
        1
  •  1
  •   Aprillion    7 年前

    不安全 , react-hooks/rules-of-hooks 只是一个 eslint rule

    这个 问题完全一样 如前所述,在 https://overreacted.io/why-do-hooks-rely-on-call-order/

    React.createElement(ImageId...) 调用JSX而不是调用普通函数:

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