Closed s-sasaki-0529 closed 1 week ago
各コンポーネントの RSC の対応状況を担保する自動テストの構成を見直し、"use client" を付与したクライアントコンポーネントの対応状況までカバーできるように仕組みを見直します。
"use client"
各コンポーネントに対して、以下のどちらかに分類し、それを満たしているかをテストしています。
A. サーバーコンポーネントとして描画できること (RSC上で使えること) B. サーバーコンポーネントで描画するとエラーが発生すること (RSC上で使えないこと)
しかし、この区分けの場合、コンポーネントに "use client" を付与してクライアントコンポーネントとした場合、それはサーバーコンポーネントには成れないのに、Aのテストにパスしてしまい、不正確な判定となってしまいます。
各コンポーネントに対して、以下の3種類のどれかに分類し、それを満たしてるかをテストします。
A. サーバーコンポーネント内で、サーバーコンポーネントとして描画できること B. サーバーコンポーネント内で、クライアントコンポーネントとして描画できること C. サーバーコンポーネントで描画するとエラーが発生すること (RSC上で使えないこと)
asis の A,B の識別は、シンプルにサーバーコンポーネント上にコンポーネントを配置し、エラーなく描画できるかをチェックするだけでした。
toBe の A,B の識別では、ランタイムで対象コンポーネントがサーバーコンポーネントなのか、クライアントコンポーネントなのかを識別する必要があります。
そのために以下のような検証コンポーネントを挟むようにしました。
const CLIENT_COMPONENT_SYMBOL = Symbol.for('react.client.reference') const isClientComponent = (actualComponent: any) => actualComponent?.$$typeof === CLIENT_COMPONENT_SYMBOL export const RSCChecker: FC<Props> = ({ actualComponent }) => { const message = isClientComponent(actualComponent) ? 'This is client component' : 'This is server component' return <p>{message}</p> }
これはドキュメントがあるとかベストプラクティスってことは全然なくて、実際に各パターンのコンポーネントを調べた結果、どうやらクライアントコンポーネントの場合は Proxy でラップされ、$$typeof フィールドにクライアントコンポーネントを示すシンボルが挿入されていることがわかりました。
$$typeof
よって、これを用いて、各コンポーネントのテスト用ページで This is client component / This is server component のどちらかを描画させ、期待している方の文字列が描画されているかをチェックすることで、A,Bの分類をできるようにします。
This is client component
This is server component
本PRの時点では、テストコード(sandbox) 以外に手を入れていないため、すべて A と C に分類され、テストが通ることを確認しています。
そのうえで、検証用の以下PRをマージした状態で確認したところ、Stack / Cluster など各コンポーネントが B に分類され、それらに依存していたせいで C になっていたコンポーネントが A になれることを確認済みです。
use client
Open in Stackblitz
pnpm add https://pkg.pr.new/kufu/smarthr-ui@5087
commit: fe60c0b
fe60c0b
概要
各コンポーネントの RSC の対応状況を担保する自動テストの構成を見直し、
"use client"
を付与したクライアントコンポーネントの対応状況までカバーできるように仕組みを見直します。asIs
各コンポーネントに対して、以下のどちらかに分類し、それを満たしているかをテストしています。
A. サーバーコンポーネントとして描画できること (RSC上で使えること) B. サーバーコンポーネントで描画するとエラーが発生すること (RSC上で使えないこと)
しかし、この区分けの場合、コンポーネントに
"use client"
を付与してクライアントコンポーネントとした場合、それはサーバーコンポーネントには成れないのに、Aのテストにパスしてしまい、不正確な判定となってしまいます。toBe
各コンポーネントに対して、以下の3種類のどれかに分類し、それを満たしてるかをテストします。
A. サーバーコンポーネント内で、サーバーコンポーネントとして描画できること B. サーバーコンポーネント内で、クライアントコンポーネントとして描画できること C. サーバーコンポーネントで描画するとエラーが発生すること (RSC上で使えないこと)
変更内容
asis の A,B の識別は、シンプルにサーバーコンポーネント上にコンポーネントを配置し、エラーなく描画できるかをチェックするだけでした。
toBe の A,B の識別では、ランタイムで対象コンポーネントがサーバーコンポーネントなのか、クライアントコンポーネントなのかを識別する必要があります。
そのために以下のような検証コンポーネントを挟むようにしました。
これはドキュメントがあるとかベストプラクティスってことは全然なくて、実際に各パターンのコンポーネントを調べた結果、どうやらクライアントコンポーネントの場合は Proxy でラップされ、
$$typeof
フィールドにクライアントコンポーネントを示すシンボルが挿入されていることがわかりました。よって、これを用いて、各コンポーネントのテスト用ページで
This is client component
/This is server component
のどちらかを描画させ、期待している方の文字列が描画されているかをチェックすることで、A,Bの分類をできるようにします。確認方法
本PRの時点では、テストコード(sandbox) 以外に手を入れていないため、すべて A と C に分類され、テストが通ることを確認しています。
そのうえで、検証用の以下PRをマージした状態で確認したところ、Stack / Cluster など各コンポーネントが B に分類され、それらに依存していたせいで C になっていたコンポーネントが A になれることを確認済みです。
マージ後の計画
use client
を付与して、すべて B に移動します