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.44k stars 430 forks source link

DOMException: Failed to execute 'replaceState' on 'History': #<Object> could not be cloned #775

Closed iamohd-zz closed 1 year ago

iamohd-zz commented 3 years ago

Versions:

Describe the problem:

I am using Vue 3 Draggable package. In the event of dragging an element, I execute Inertia.put method and pass some data to Laravel. This is where this exception occurs.

Steps to reproduce:

For example, in Laravel pass a project with a list of columns to your view. Then use the Draggable component as following:

<Draggable
    v-model="project.columns"
    group="columns"
    item-key="id"
    @end="onColumnPositionChanged"
>
    <template #item="{element: column}">
        <KanbanColumn
             :column="column"
             :key="column.id"
         />
    </template>
</Draggable>

In event of onColumnPositionChanged, trigger Inertia.put method

const onCardPositionChanged = () => {
    Inertia.put('/some-route');
};
SDIjeremy commented 1 year ago

Still having this problem

LarryBarker commented 11 months ago

This issue just started popping up for us recently as well :\


    at History.replaceState (http://localhost:5173/node_modules/.vite/deps/@sentry_vue.js?v=351ebc3d:953:38)
    at C.replaceState (http://localhost:5173/node_modules/.vite/deps/@inertiajs_vue3.js?v=351ebc3d:5784:35)
    at C.saveScrollPositions (http://localhost:5173/node_modules/.vite/deps/@inertiajs_vue3.js?v=351ebc3d:5645:10)
    at C.resetScrollPositions (http://localhost:5173/node_modules/.vite/deps/@inertiajs_vue3.js?v=351ebc3d:5650:14)
    at http://localhost:5173/node_modules/.vite/deps/@inertiajs_vue3.js?v=351ebc3d:5776:19```

Going to walk back through some commits and see if we can figure out where it started happening, but it has been very difficult to debug so far.

@reinink what would it take to get you to look into this? is this still a thing with 1.0? thanks!
SDIjeremy commented 11 months ago

@LarryBarker the issue seems to happen when you are using or manipulating props directly/indirectly that are large or complex. a work around is as stated above, to encode and decode the prop data.

LarryBarker commented 11 months ago

@LarryBarker the issue seems to happen when you are using or manipulating props directly/indirectly that are large or complex. a work around is as stated above, to encode and decode the prop data.

@SDIjeremy yeah, thank you, I did see that. It's a tricky issue to debug if you have many props being passed to the component.

alagiesellu commented 11 months ago

I had the same issue when using usePage() inside of the state function of Pinia.

Before:

    state: () => {
        return {
            cart: usePage().props.value.cart as Cart,
        }
    },

    actions: {
        setQuantity(product_id: number, quantity: any) {
            // Here an update to the cart happened
            this.cart.products = this.cart.products.map(productInCart => {
                if (productInCart.product_id !== product_id) {
                    return productInCart;
                }

                return {
                    ...productInCart,
                    quantity: quantity,
                }
            })

            // Then this PUT request will error
            Inertia.put('/cart/set', {
                cart_id: this.cart.id,
                product_id,
                quantity,
            }, {
                preserveScroll: true,
                only: ['cart', 'errors'],
            });
        },
    },

I've fixed it by changing the state to this:

    state: () => {
        const cart =  JSON.parse(JSON.stringify(usePage().props.value.cart))

        return {
            cart: cart as Cart,
        }
    },

I think it has something to do with the package @vueuse/core conflicting with @inertiajs/vue3

I am having the same error on pages where I use useIntersectionObserver

@antfu and team should help out here.

eurairapelli commented 8 months ago
<Draggable
    v-model="project.columns"
    group="columns"
    item-key="id"
    @end="onColumnPositionChanged"
>
    <template #item="{element: column}">
        <KanbanColumn
             :column="column"
             :key="column.id"
         />
    </template>
</Draggable>

Try changing v-model="project.columns" to :list="project.columns" i was having a similar issue and this seams to have solved it for me

Source: https://github.com/SortableJS/vue.draggable.next#list

Its work. I do this, list into list (laravel with:tasks) and works change to :list

rkyoku commented 8 months ago

@reinink I have this bug when dynamically adding a function to an object/prop in Svelte (export let mystuff; mystuff.onEvent = () => {})

This is extremely handy and saves from using events (which can only happen AFTER mount, at least in Svelte), and the syntax is also shorter and more intuitive than events, and it is less restrictive for devs (why on Earth wouldn't we be allowed to use functions in javascript?)

Maybe remove functions before serializing? Problem solved. No impact on Inertia.

jamesst20 commented 5 months ago

2024 - Svelte 5

  let { fieldGroups = [] }: Props = $props();
  // Crash
  structuredClone(fieldGroups);
  // Ok
  structuredClone($state.snapshot(field groups))

Anything related to the state will not be "cloneable" so it's very likely this error will be triggered often.

$state.snapshot is required for deep cloning.

@inertiajs/core doesn't like proxy object

-- A possible global fix could be doing this. This is more of a hack because I don't see this getting fixed anytime soon

  import { router } from '@inertiajs/svelte'

 createInertiaApp({
    ...
    setup({ App, el }: any) {
      const orig = router.replaceState;
      router.replaceState = function (page: any) {
        orig.call(this, JSON.parse(JSON.stringify(page)));
      };

      mount(App, { target: el });
    },
pedroborges commented 1 month ago

@jamesst20 just read the whole thread but honestly I'm not sure how I can reproduce this issue. If you or anyone can tell me how to reproduce it with Inertia I'd be happy to debug and work on a fix.

jamesst20 commented 1 month ago

@jamesst20 just read the whole thread but honestly I'm not sure how I can reproduce this issue. If you or anyone can tell me how to reproduce it with Inertia I'd be happy to debug and work on a fix.

@pedroborges Thanks for the quick response

Here is a simple reproduction exemple (open chrome inspector console to see errors) REPL

This is what happens internally in @inertiajs/core see here https://github.com/inertiajs/inertia/blob/master/packages/core/src/router.ts#L490C5-L490C52 so basically when we click a link that uses the router (i.e use:inertia on an anchor tag) it will crash because it will want to preserve current state

Solutions:

Replacing

window.history.replaceState(state, '', window.location.href)

with any of

window.history.replaceState($state.snapshot(state), '', window.location.href)
window.history.replaceState(JSON.parse(JSON.stringify(state)), '', window.location.href)
window.history.replaceState(lodashDeepClone(state), '', window.location.href)