-
Notifications
You must be signed in to change notification settings - Fork 26.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client components used only inside server actions are not added to the module graph #58125
Comments
I am facing the same situation in an This is my "use client";
import { Suspense, useMemo } from "react";
import { usePropsChangedKey } from "@/app/hooks";
import useSWR from "swr";
const fetcher = (action, props) =>
new Promise((r) => setTimeout(async () => r(await action(props))));
const fetcherSWR = ([, action, props]) => fetcher(action, props);
const Error = ({ errorMessage }) => <>Something went wrong: {errorMessage}</>;
const getReader = () => {
let done = false;
let promise = null;
let value;
return {
read: (fetcher) => {
if (done) {
return value;
}
if (promise) {
throw promise;
}
promise = new Promise(async (resolve) => {
try {
value = await fetcher();
} catch (error) {
value = <Error errorMessage={error.message} />;
} finally {
done = true;
promise = null;
resolve();
}
});
throw promise;
},
};
};
const Read = ({ fetcher, reader }) => {
return reader.read(fetcher);
};
const ReadSWR = ({ swrArgs, fetcher }) => {
return useSWR(swrArgs, fetcher, {
revalidateOnFocus: false,
revalidateOnReconnect: false,
suspense: true,
}).data;
};
export default function Action({
action,
children = <>loading...</>,
isSWR = false,
...props
}) {
const propsChangedKey = usePropsChangedKey(...Object.values(props));
const reader = useMemo(() => getReader(), [propsChangedKey]);
const propsForSWR = useMemo(() => props, [propsChangedKey]);
const swrArgs = useMemo(
() => [propsChangedKey, action, propsForSWR],
[action, propsForSWR, propsChangedKey]
);
return (
<Suspense fallback={children}>
{isSWR ? (
<ReadSWR swrArgs={swrArgs} fetcher={fetcherSWR} />
) : (
<Read fetcher={() => fetcher(action, props)} reader={reader} />
)}
</Suspense>
);
} This is the hook (for those who are curious about it): import { useState, useEffect, useRef } from "react";
export function usePropsChangedKey(...args) {
const [propsChangedKey, setPropsChangedKey] = useState(0);
const isFirstRenderRef = useRef(false);
useEffect(() => {
isFirstRenderRef.current = true;
}, []);
useEffect(() => {
if (!isFirstRenderRef.current) {
setPropsChangedKey((k) => k + 1);
} else {
isFirstRenderRef.current = false;
}
}, [...args]);
return propsChangedKey;
} This is how you call the "use client";
import Action from "@/app/action";
import { greeting } from "@/app/actions/greeting";
import { useState } from "react";
export default function Client1() {
const [userId, setUserId] = useState(1);
return (
<>
<Action action={greeting} userId={userId} />
<button
onClick={() => {
setUserId(2);
}}
>
click
</button>
</>
);
} And this is the "use server";
import Greeting from "@/app/action-components/greeting";
import MyError from "@/app/action-components/my-error";
const DELAY = 500;
const users = [
{ id: 1, username: "roggc" },
{ id: 2, username: "roger" },
];
export async function greeting({ userId }) {
try {
const username = await new Promise((r) => {
setTimeout(() => {
const user = users.find((u) => u.id === userId);
if (user) {
r(user.username);
}
}, DELAY);
});
// throw new Error("crash!");
return <Greeting username={username} />;
} catch (error) {
return <MyError errorMessage={error.message} />;
}
} Now, without the workaround commented at the beginning, you get this error:
The workaround, as I said, is to import the server action in a server component, for example the import { Inter } from "next/font/google";
import { greeting } from "@/app/actions/greeting"; // <-- this is necessary, if not fails to compile
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
} |
I'm facing the same issue. |
Link to the code that reproduces this issue
https://github.com/Dwlad90/elegant-cloud-zckzqc/tree/draft/goofy-mountain
To Reproduce
npm i
next dev
)" Error: Could not find the module "/Users/vladislavbuinovski/Projects/elegant-cloud-zckzqc/components/SA_CLNT_Component/Component.tsx#" in the React Client Manifest. This is probably a bug in the React Server Components bundler."
Server: Test server
(Test server
should be pink with a yellow background)Current vs. Expected behavior
Client side modules imported only in a server action module are not included in the React Client Manifest. They should be and the missing style should show up
Verify canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 23.1.0: Mon Oct 9 21:27:24 PDT 2023; root:xnu-10002.41.9~6/RELEASE_ARM64_T6000 Binaries: Node: 18.18.2 npm: 10.1.0 Yarn: 1.22.19 pnpm: 8.9.2 Relevant Packages: next: 14.0.2-canary.18 eslint-config-next: 14.0.2-canary.18 react: 18.2.0 react-dom: 18.2.0 typescript: 5.2.2 Next.js Config: output: N/A
Which area(s) are affected? (Select all that apply)
App Router
Additional context
No response
The text was updated successfully, but these errors were encountered: