Functions cannot be passed directly の直し方
実際に出るエラー
Server Component から Client Component へ、関数を props で渡したときに出るエラーです。
いつ出るのか
Server Component から、'use client' を書いた部品へ関数を渡すと出ます。
// app/page.tsx(Server Component)
import { Price } from './Price' // Price は 'use client'
export default function Page() {
return <Price value={1200} format={(n) => `${n} 円`} />
}
実機で、ビルドが止まり、文言の下にどの props が関数だったか(format: function format)が示されました。
Event handlers cannot be passed との違い
同じ「関数を渡した」でも、props の名前で文言が変わります。
| props | 文言 |
|---|---|
| onClick・onAdd など on で始まる名前 | Event handlers cannot be passed to Client Component props. |
| format・render・children など、それ以外 | Functions cannot be passed directly to Client Components … |
原因は同じです。on で始まる名前のときの直し方は Event handlers cannot be passed の直し方にまとめています。
children に関数を書いても出る
タグの間に書いたものも children という props です。一覧の各行の見た目をページ側で決めたくて、children に関数を書く形(render prop)も同じ文言になりました。
<List items={['a', 'b']}>{(s) => <b>{s}</b>}</List>
指されたのは children: function children でした。
なぜ渡せないのか
Server Component が返したものは、いったん値だけの形に変えてブラウザへ送られます。関数はその形にできません(Server から Client へ渡せる props の値)。
直し方
実機で、次のどれもビルドが通りました。
1. 関数ごと Client Component の中へ移す
整形のように画面の中で済む処理は、受け取る側で行います。
'use client'
export function Price({ value }: { value: number }) {
return <p>{value.toLocaleString('ja-JP')} 円</p>
}
2. サーバーで処理して、結果だけ渡す
関数の結果が文字列や数値なら、ページ側で呼んで結果を渡します。文言の後半「Or maybe you meant to call this function」は、この形を指しています。
children に関数を書いていた場合は、ページ側で描いた要素を配列で渡せます。実機で、太字にした要素の配列はそのまま送れて表示されました。
<Rows rows={items.map((s) => <b key={s}>{s}</b>)} />
3. サーバーで動かしたい関数なら 'use server'
保存のようにサーバーで動かす必要がある関数は、'use server' を付けて Server Function にすると渡せます。文言の前半「unless you explicitly expose it by marking it with "use server"」は、この形を指しています。
async function save(n: number) {
'use server'
await db.save(n)
}
export default function Page() {
return <Saver save={save} />
}
Server Function は、ブラウザから呼べる入口になります。受け取る値を必ず確かめます(Server Function の渡し方)。
まとめ
- 関数は Server Component から Client Component へ渡せない。名前が on で始まらないとこの文言になる
- children に関数を書く形も同じ
- 画面の中で済むなら Client Component へ移す。結果だけで済むなら結果を渡す。サーバーで動かすなら 'use server'
出典
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。