user824624
user824624

Reputation: 8056

Error: async/await is not yet supported in Client Components in next.js

I am using next.js on "next": "13.4.19". the project structure is --app -- layout.tsx -- page.tsx -- [id] --page.tsx

in the [id] page.tsx,

"use client"

import { Editor } from '@/components/editor';
import { useState, useRef, useEffect, useMemo } from 'react'

export default async function PipelineDesignerEditorPage(
  { params }: { params: { pipelineId: string } }
) {
  console.log('params.pipelineId',params.pipelineId);

  const [loding, setLoding] = useState(false);
  const [pipelineData, setPipelineData] = useState({});

  useEffect(() => {
    setLoding(true);
    let data = getPipeline(params.pipelineId);
    setPipelineData(data);
    setLoding(false);
  }, []);

  return (
    <div style={{ width: '100%', height: `calc(100vh - 65px)` }}>
      <Editor pipeline={pipeline} />
    </div>
  )
}

an error 'Error: async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding 'use client' to a module that was originally written for the server.' appears.

I found this page is being rendered in the server side, so I modified a bit

'user client'
import { Editor } from '@/components/editor';
import { getPipeline } from '@/lib/pipelines/storage';
import { useState, useRef, useEffect, useMemo } from 'react'

export default async function PipelineDesignerEditorPage(
  { params }: { params: { pipelineId: string } }
) {
  console.log('params.pipelineId',params.pipelineId);
  const pipeline = await getPipeline(params.pipelineId);
  
  const [loding, setLoding] = useState(false);
  useEffect(() => {
    console.log('useEffect');
    setLoding(true);
  }, []);

  return (
    <div style={{ width: '100%', height: `calc(100vh - 65px)` }}>
      <Editor pipeline={pipeline} />
    </div>
  )
}

it still doesn't work unless useEffect and useState is removed away.

Does it mean I can't use useState and useEffect in app->[id]->page.tsx, what about click, loading actions which needs to use useState and useEffect

Upvotes: 26

Views: 69473

Answers (6)

Avnish Kumar Sharma
Avnish Kumar Sharma

Reputation: 1

Dude, it might occur cuz your <Editor pipeline={pipeline} /> is a server component, in nextjs we can't import a server component in client component.

To fix this you just need go to the parent component of this PipelineDesignerEditorPage and pass <Editor /> component as a prop,

Or you can pass as a children also :

<PipelineDesignerEditorPage>
  <Editor />
</PipelineDesignerEditorPage>

and add children in this component :

'user client'
import { Editor } from '@/components/editor';
import { getPipeline } from '@/lib/pipelines/storage';
import { useState, useRef, useEffect, useMemo } from 'react'

export default async function PipelineDesignerEditorPage(
  { params, children }: { params: { pipelineId: string }; children : React.ReactNode}
) {
  console.log('params.pipelineId',params.pipelineId);
  const pipeline = await getPipeline(params.pipelineId);
  
  const [loding, setLoding] = useState(false);
  useEffect(() => {
    console.log('useEffect');
    setLoding(true);
  }, []);

  return (
    <div style={{ width: '100%', height: `calc(100vh - 65px)` }}>
      <Editor pipeline={pipeline} />
    </div>
  )
}

hope this helps..!

Upvotes: 0

Georgi Yankov
Georgi Yankov

Reputation: 441

I used to get this error after changing the name of one prop and not updating the declaration in the parent component.

Upvotes: 1

Daniel De Le&#243;n
Daniel De Le&#243;n

Reputation: 13639

I got this error, when I accidentally define a function component as async function and call a valid async function inside of it.

async function MyComponent(){
   ...
   useEffect( () =>{
      asyncFunction().then(value => setInfo(value));
   },...)       
...
}

So just remove the async operator from the function component declaration and will work fine:

function MyComponent(){
   ...
   useEffect( () =>{
      asyncFunction().then(value => setInfo(value));
   },...)       
...
}

Upvotes: 4

Quang Le
Quang Le

Reputation: 435

I used to get the same error when I tried applying 'use client' for the whole page.

My solution is removing the async keyword. In this case, use:

export default function PipelineDesignerEditorPage

instead of:

export default async function PipelineDesignerEditorPage

Upvotes: 41

Rajat Das
Rajat Das

Reputation: 167

Fetching data in my page.tsx was quite frustrating as it would required me to do prop drilling. Fortunately, I discovered a more effective solution. By utilizing the dynamic function from the next/dynamic package, I was able to address the issue. Here's an example:

const ChatWelcomeContent = dynamic(() => import("./chat-welcome-content"), {
  ssr: true,
});

This resolves the error:

"Error: async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding 'use client' to a module that was originally written for the server."

Hope it helps!

Upvotes: 2

grekier
grekier

Reputation: 3697

You are mixing client and server components. As the error says, async/await is only supported in server component (without "use client"). But, as you mentioned, useState and useEffect (or events like click) etc... are only supported in client components.

The solution is to split the 2 in 2 different components. Typically the page.tsx would be a server component where you fetch data and pass those to a child client component as parameter(s) where you can have state and events if needed.

On a specific note, you probably should have state and effect in the Editor or look at Suspense. See example under https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming#example

Upvotes: 25

Related Questions