【问题标题】:Property *** does not exist on type 'ExoticComponent<any>属性 *** 在类型 'ExoticComponent<any> 上不存在
【发布时间】:2021-11-29 16:46:17
【问题描述】:

我尝试在 React / Next.js 项目中进行代码拆分,但遇到了障碍。

我正在关注这里的操作方法:https://reactjs.org/docs/code-splitting.html

在此处导入:

const { SHA512 } = React.lazy(() => import("crypto-js"));

并在这里使用useEffect

useEffect(() => {
    setTimeout(() => {
      let window2: any = window;
      if (window2.bp && process.env.NEXT_PUBLIC_BARION_ID) {
        const { totalPriceInt, unitPriceInt } = calcUnitAndTotalPrice(
          startPaymentIn,
          buyTicketData
        );
        window2.bp("track", "initiateCheckout", {
          contentType: "Product",
          currency: "HUF",
          id: startPaymentIn.eventId,
          name: buyTicketData?.name,
          quantity: startPaymentIn.quantity ?? 1.0,
          unit: "db",
          imageUrl: `https://ticket-t01.s3.eu-central-1.amazonaws.com/${buyTicketData?.imgId}_0.cover.jpg`,
          list: "ProductPage",
        });
        window2.bp("track", "setUserProperties", {
          userId: SHA512(getTempUserId(localStorage)).toString(), // <--- HERE
        });
      }
    }, 4000);
  }, []);

但得到这个错误:

./components/LoginAndRegistration.tsx:25:9
Type error: Property 'SHA512' does not exist on type 'ExoticComponent<any> & { readonly _result: ComponentType<any>; }'.

  23 | import { GoogleLogin } from "react-google-login";
  24 | import axios from "axios";
> 25 | const { SHA512 } = React.lazy(() => import("crypto-js"));
     |         ^
  26 | 
  27 | interface LoginAndRegistrationProps {
  28 |   isRegistration: boolean;
error Command failed with exit code 1.

你知道为什么会出错吗?

在没有延迟加载的情况下工作之前:

import { SHA512 } from "crypto-js";

我也尝试了 Next.js 解决方法:

import dynamic from "next/dynamic";
const { SHA512 } = dynamic(() => import("crypto-js"));

但出现此错误:

Type error: 'await' expressions are only allowed within async functions and at the top levels of modules.

  130 | 
  131 |   useEffect(() => {
> 132 |     const { SHA512 } = await import("crypto-js");
      |                        ^
  133 |     setTimeout(() => {
  134 |       let window2: any = window;
  135 |       if (window2.bp && process.env.NEXT_PUBLIC_BARION_ID) {

【问题讨论】:

    标签: reactjs next.js code-splitting


    【解决方案1】:

    import("crypto-js") 返回一个承诺,一旦解决,就拥有模块的 API。它不是 React 组件,因此您不能在其上使用 React.lazy()。 (您可以将React.lazy 与导出组件的模块一起使用。)

    如果你需要在一个 React 组件中懒加载crypto-js,然后做一些事情,你可以做

    function MyComponent() {
      const [cryptoJs, setCryptoJs] = React.useState(null);
      React.useEffect(() => import("crypto-js").then(setCryptoJs), []);
      React.useEffect(() => {
        if(!cryptoJs) return;  // not loaded yet...
        const { SHA512 } = cryptoJs;
        // ...
      }, [cryptoJs]);
    }
    

    function MyComponent() {
      React.useEffect(() => {
        import("crypto-js").then(({ SHA512 }) => {
          // ...
        });
      }, []);
    }
    

    但是,根据您的捆绑器和捆绑器配置,最好只对库使用常规import,而不是延迟导入(例如使用React.lazy)具有需要该库的组件的模块。

    【讨论】:

    • 延迟加载组件而不是模块?对我来说,似乎 webpack - 在我的设置中 - 不够聪明,如果在任何地方导入模块,即使它根本没有在组件上使用它也会下载。
    • 我这里还有一个问题,但是图标看起来有点相似,你怎么看? stackoverflow.com/questions/69517872/…
    • 导入模块可能会产生副作用,所以是的,静态导入会拉入模块,除非你告诉 Webpack 模块是纯模块并且没有副作用。
    【解决方案2】:

    here所述,

    React.lazy 采用一个必须调用动态import() 的函数。这必须返回一个 Promise 解析为一个带有 default 导出包含 React 组件的模块

    因此,您不能将 React.lazy 用于 crypto-js 包,因为它不会导出 React 组件。

    你可以在 NextJS 中使用dynamic import。因此:

    useEffect(() => {
      import('crypto-js').then(({ SHA512 }) => {
        // Use SHA512 here
      });
    }, []);
    

    【讨论】:

    • useEffect 函数不能是 async 由于隐式返回承诺。
    • @AKX 感谢您指出这一点。我已经更新了代码。
    猜你喜欢
    • 2021-02-08
    • 2019-09-20
    • 2018-09-09
    • 2019-12-31
    • 2022-12-17
    • 2017-10-20
    • 2017-01-14
    • 2020-01-11
    • 2016-09-01
    相关资源
    最近更新 更多