I try to do code split in React / Next.js project, but facing with obstacles.
I am following the howto here: https://reactjs.org/docs/code-splitting.html
Importing here:
const { SHA512 } = React.lazy(() => import("crypto-js"));
and using in useEffect
here:
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);
}, []);
but get this error:
./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.
Do you know maybe why it is wrong?
Before it worked without lazy loading:
import { SHA512 } from "crypto-js";
I also tryed Next.js workaround:
import dynamic from "next/dynamic";
const { SHA512 } = dynamic(() => import("crypto-js"));
but got this error:
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) {
CodePudding user response:
As mentioned here,
React.lazy
takes a function that must call a dynamicimport()
. This must return aPromise
which resolves to a module with adefault
export containing a React component.
So you can't use React.lazy
for the crypto-js
package because it doesn't export a React component.
You can use dynamic import in NextJS. As such:
useEffect(() => {
import('crypto-js').then(({ SHA512 }) => {
// Use SHA512 here
});
}, []);
CodePudding user response:
import("crypto-js")
returns a promise, that once resolved, has the API of the module. It's not a React component, hence you can't use React.lazy()
on it. (You could use React.lazy
with a module that exports a component.)
If you need to lazily load crypto-js
within a React component, and then do things, you can do
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]);
}
or
function MyComponent() {
React.useEffect(() => {
import("crypto-js").then(({ SHA512 }) => {
// ...
});
}, []);
}
However, depending on your bundler and bundler configuration it might be better to just use a regular import
for the library, and instead lazily import (e.g. with React.lazy
) the module that has this component that requires the library.