inertiajs / inertia

Inertia.js lets you quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and controllers.
https://inertiajs.com
MIT License
6.3k stars 423 forks source link

[1.x] Fix "DataCloneError: <Object> could not be cloned" #1967

Closed pedroborges closed 2 weeks ago

pedroborges commented 3 weeks ago

This bug has been around for a while in Inertia.js (see timeline below), and after digging into it with @jamesst20's help, we figured out the core issue: Inertia is trying to serialize proxy objects when it saves data to the history state. You might run into this using useForm (fixed in 2021), router.remember, or even just scrolling, as Inertia saves scroll positions in history.

history.replaceState uses structuredClone, which throws DataCloneError if it hits anything non-serializable.

To fix it, I’m using JSON.parse(JSON.stringify()). This is great for simple data structures, and it automatically strips out stuff like functions that can cause issues. It’s lighter and more efficient for this specific case than using lodash.cloneDeep(), which keeps things like functions around (and we don’t need that here).

This issue has mostly affected users of the Vue.js adapter since Vue uses proxy objects for its reactivity system. However, it can impact anyone using front-end libraries that rely on proxies, like Svelte 5, which is rolling out its own reactive system based on runes.

Reproducible

Stack trace

UnhandledPromiseRejectionWarning: DataCloneError: Proxy object could not be cloned.
Uncaught (in promise) DOMException: The object could not be cloned. router.ts:397:4
    replaceState router.ts:398
    saveScrollPositions router.ts:73
    resetScrollPositions router.ts:91
    g router.ts:381
    (Async: promise callback)
    g router.ts:379
    (Async: promise callback)
    setPage router.ts:373
    handleInitialPageVisit router.ts:52
    init router.ts:41
    setup app.js:43

179274326-cc3b66c8-852a-4323-9a2f-92092312afdd

Timeline

I built this timeline to help me keep track of occurrences relative to the previous attempts to fix this issue.

Last activity Issue / PR
Oct 2020 #278
Oct 2020 #295
Oct 2020 #297 first attempt to fix
Mar 2021 #552
Mar 2021 #582
Mar 2021 #587 last attempt to fix
Apr 2021 #1021
Jun 2021 #578
Jul 2021 #776 rejected PR
Aug 2021 #730
Aug 2021 #854
Dec 2021 #940
Jul 2022 #309
Sep 2022 #1227
Oct 2022 #1246
Nov 2022 #1340
May 2024 #775 60 comments

Fixes #278, #295, #297, #309, #552, #578, #582, #587, #730, #775, #776, #854, #940, #1021, #1227, #1246, #1340