Next and use() causing infinite requests.
Answered
Bombay-duck posted this in #help-forum
Bombay-duckOP
Hi there. I’m encountering an error in my NextJS app. For some background, I am loading some data from FireBase based on an ID. Here is my page component:
The error I am encountering is in the
export default function ProjectPage() {
console.log("Loading project page");
const params = useParams<{ id: string }>();
const router = useRouter();
const backToProjects = () => {
router.back();
};
return (
<EnsureAuth>
<ErrorBoundary fallback={<p>An error occured loading the project.</p>}>
<Suspense fallback={<Spinner />}>
<UserProjectDetails projectId={params.id} onBack={backToProjects} />
</Suspense>
</ErrorBoundary>
</EnsureAuth>
);
}The error I am encountering is in the
UserProjectDetsils component. This component loads data from FireBase and displays it in a UI. The issue I am having is that there seems to be an infinite loop somehow that is repeatedly calling the function to load the data, for some reason. I’ve included the definition of the UderProfileDetails components in the comments.Answered by Bombay-duck
Found the solution. It turns out React Query isn't playing well with how I am using use(). So, I just need to remove the mutation and just call the async function directly.
8 Replies
Bombay-duckOP
Here is the code for the
UserProjectDetails component:export default function UserProjectDetails({
projectId,
onBack,
}: UserProjectDetailsProps) {
const [_, { getProjectById }] = useProjectsContext();
console.info("Loading project " + projectId);
const project = use(getProjectById(projectId));
console.info("Project loaded");
if (!project) {
console.info("Project not found");
return notFound();
}
return (
<section className="overflow-x-auto">
<UserProjectInfo project={project} onBack={onBack} />
<Tabs aria-label="Full width tabs" style="fullWidth">
<Tabs.Item active title="Overview" icon={HiUserCircle}>
Overview goes here.
</Tabs.Item>
<Tabs.Item title="My Betas" icon={HiUserCircle}>
My Betas go here
</Tabs.Item>
<Tabs.Item title="My Surveys" icon={MdDashboard}>
My Surveys go here.
</Tabs.Item>
</Tabs>
</section>
);
}I think the problem may be from my use of React’s [use() hook](https://react.dev/reference/react/use). However, according to the [Suspense Docs](https://react.dev/reference/react/Suspense) I need to use the
use() hook to trigger the Suspense component since my getProjectById() returns a promise containing the project details.Also, the reason I suspect it’s the
use() hook that is causing the error is because in my logs, console.info("Loading project " + projectId); is being printed infinite times.Bombay-duckOP
Bombay-duckOP
Lastly, I don't know if this will help. But, here is the definition of
getProjectById() in the ProjectsContext: const getProjectByIdMutation = useMutation<Project | null, Error, string>({
throwOnError: true,
mutationKey: ["get-project-for-id"],
mutationFn: async (id) => {
if (user) {
return await getProjectForId(id, user.id);
} else {
throw new UnauthorizedException();
}
},
});
/**
* getProjectById()
*
* gets a project by its ID.
* @throws UnauthorizedException when the client is unauthenticated.
*/
const getProjectById = async (id: string): Promise<Project | null> => {
return await getProjectByIdMutation.mutateAsync(id);
};The
getProjectForId() function just makes a call to Firestore to retrieve the project. export const getProjectForId = async (
projectId: string,
userId: string,
correlation: string = uuid(),
): Promise<Project | null> => {
try {
const projectRef = doc(database, CollectionNames.Projects, projectId);
const record = await getDoc(projectRef);
let project: Project | null = null;
if (record.exists()) {
const data = record.data();
// ensure the user retrieving the project owns it.
if (data.owner !== userId) {
throw new ForbiddenException();
}
// convert the record to a project
project = {
id: data.id,
created_on: DateTime.fromISO(data.created_on),
description: data.description,
name: data.name,
owner: data.owner,
};
}
return project;
} catch (e) {
if (e instanceof ForbiddenException) {
throw e;
} else {
throw new ServerException();
}
}
};Bombay-duckOP
Bump
Bombay-duckOP
Found the solution. It turns out React Query isn't playing well with how I am using use(). So, I just need to remove the mutation and just call the async function directly.
Answer