🦧

Client ComponentsでSuspense+use使用時のエラー(Not implemented)の解決方法

2022/11/01に公開

環境

  • react 18.2.0
  • next 13.0.0

やっていたこと

Reactを17から18に、Next12から13にアップデートして、Client Componentsでfetchを含むコードを使用してcache + use + Suspenseなどを利用したところ、エラーが発生し、buildできなくなった。

結論

結論から言うと、SWRなどを使うか、Server Componentsにfetch系処理を移行して使う。
以下は、その経緯。

該当コード

PizzaList component

fetch api, cache + use

// PizzaList.tsx
const getPizza = cache(
  (id: string): Promise<Pizza[]> =>
    fetch(`${process.env.NEXT_PUBLIC_API_HOST}/pizza/${id}`).then((res) =>
      res.json()
    )
);

const PizzaList = () => {
  const pizza = use(getPizza(id));
  return (
    <>
      {pizza.map((p) => {
        return (
	  <>
	    <div>{p.id}</div>
	    <div>{p.name}</div>
	  </>
	);
      })}
    </>
  );
};

export default PizzaList;

Pizza screen

dynamic import, Suspense

// pizza.tsx
'use client';

const PizzaList = React.lazy(() => import('@/components/pizza/PizzaList'));

const Pizza = () => {
  return (
    <Suspense fallback={<Loading />}>
      <PizzaList />
    </Suspense>
  );
};

export default Pizza;

エラーログ

上記コードを動かすとエラーが発生した。

Uncaught Error: Not implemented.
    at updateDehydratedSuspenseComponent (react-dom.development.js?160d:23538:1)
    at updateSuspenseComponent (react-dom.development.js?160d:23235:1)
    at beginWork (react-dom.development.js?160d:24544:1)
    at beginWork$1 (react-dom.development.js?160d:31617:1)
    at performUnitOfWork (react-dom.development.js?160d:30549:1)
    at workLoopSync (react-dom.development.js?160d:30434:1)
    at renderRootSync (react-dom.development.js?160d:30387:1)
    at performConcurrentWorkOnRoot (react-dom.development.js?160d:29662:1)
    at workLoop (index.js?82e4:10:3922)
    at flushWork (index.js?82e4:10:3630)
    at MessagePort.performWorkUntilDeadline (index.js?82e4:10:1812)

https://beta.nextjs.org/docs/data-fetching/fetching#example-fetch-and-use-in-client-components
Example: fetch and use in Client Components

if you need to fetch data in a Client Component, we recommend using a third-party library

しばらくの間は、ClientComponentsで使う時はSWRなどを使用するのが良さそう。そう考えると、fetchは現時点ではSWRを使うか、ServerComponentsに入れてしまうのがベターだろう。

参考リンク

https://reactjs.org/docs/error-decoder.html/?invariant=248

https://nextjs.org/docs/messages/prerender-error

https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md
基本的にServerComponentsならasync/awaitで書いて、ClientComponentsはcache+useで書くというルール。

Discussion