1

I am getting a strange behaviour where NextJs lets me include the 'use client' directive at the top of my file while still letting me declare the component with async, like below:

'use client';

import React, { useState } from 'react';

const TestComponent = async () => {
  const [randomNumber, setRandomNumber] = useState(null);

  return (
      <div>
        <div> {randomNumber} </div>
        <button onClick={() => setRandomNumber(Math.random())}>Set state</button>
      </div>
  );
};

export default TestComponent;

I would have expected this to throw a runtime error and crash my application because I have mixed 'use client' with an async component, as is suggested here.

But all I get is a console warning and my component still runs fine. Weirdly, it acts kind of like a server component as the loading component is shown whenever I run setRandomNumber almost as if it was fetching data from a server component (I declare the loading component as a top-level component as is suggested by the nextJS docs). All of my console.logs are output in the client console (i.e. on the browser).

Is this some new functionality where your application doesn't break if you mix 'use client' with an async component?

My loading component:

const Loading = () => {
  return <p>Loading...</p>;
};

export default Loading;

My project structure:

test-app/src/app
├── test
│   └── page.js # my TestComponent page
├── page.js # just the default NextJS index page
├── loading.js # my custom top-level loading page
└── layout.js # the default layout

Update

So I investigated this a bit more. I found that my top-level loading component is preventing the usual: 'Hooks are not supported inside an async component' error from appearing (although I do get a console warning). Interestingly, when I remove my top level loading component the error does show normally during runtime when I click the 'set state' button (i.e. the error takes over the entire page). But if I include a top-level loading component in my project then the page will just show the 'loading' message as defined in the component, and the app will work just fine.

I tested this on a completely clean NextJs project with just the TestComponent above and a top-level loading component, and I still get the same behaviour. I am also able to build the project successfully and the app still runs ok (although again, I get a warning when the project builds).

Is this the expected behaviour? Perhaps this is just the way it is? It feels a bit confusing to throw an error under one set of circumstances but then it allows the project to run under other certain circumstances, e.g. if you include a loading component.

4
  • Can you show the reset of your page code?
    – grantmx
    Commented Jan 31, 2024 at 19:30
  • 1
    You have a typo. Compare your export with the component/function.
    – Stefan
    Commented Jan 31, 2024 at 22:48
  • Good catch @Stefan! TestComponent is not exported and is likely not in the RSC build. Yet testComponent likely is but just as an undeclared object.
    – grantmx
    Commented Feb 1, 2024 at 10:05
  • 1
    Ah yes, that was a typo in my post here. The actual implementation in my project had the correct export. I've now edited my post.
    – jhughes982
    Commented Feb 1, 2024 at 12:22

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.