😎

【Inertia.js】[object Object] could not be cloned.の対処法

2023/01/06に公開

背景

Laravel + Inertia.js + Vue3でSPA開発を行なっていました。
そして、チャネルトークのSPA用スクリプト導入を行なったところエラー発生しました。

https://developers.channel.io/docs/web-installation#single-page-application

実装

チャネルトークの起動には、PluginKeyが必須です。
shareInertiaData.phpからusePage関数経由でPluginKeyを取得して使用していました。

shareInertiaData.php
public function handle(Request $request, callable $next)
{
    Inertia::share(['channelTalk' => [
        'pluginKey' => 'my-plugin-key',
    ]]);

    return $next($request);
}
channel-talk.js
const page = usePage();

if (page.props.value.channelTalk) {
    // チャネルトーク起動
  ChannelService.boot(page.props.value.channelTalk);
}

エラー

usePage関数から取得したPluginKeyをそのままChannelService.boot関数の引数に渡すと以下のエラーが発生しました。

Uncaught DOMException: Failed to execute 'structuredClone' on 'Window': [object Object] could not be cloned.

原因

inertia.jsのusePage()関数から取得できるProxyオブジェクトをそのまま使っていたのが原因でした。

inertia.jsのリポジトリにも似たような現象が報告されていた。
https://github.com/inertiajs/inertia/issues/775

解決策

JSON.parse関数とJSON.stringify関数を使い、Proxyオブジェクトを変換する。

JSON.parse(JSON.stringify(usePage().props));

下記のように実装を修正すれば、私のエラーも無事消えました。

channel-talk.js
const page = usePage();

if (page.props.value.channelTalk) {
    // チャネルトーク起動 
- ChannelService.boot(page.props.value.channelTalk);
+ ChannelService.boot(JSON.parse(JSON.stringify(page.props.value.channelTalk)));
}

Discussion