inertia
inertia copied to clipboard
Fix <Render /> component to respect "preserveState"
Issues with the page component rendering in the Svelte adapter have been reported a couple time (see: #1621, #1733). The last attempt to solve this (#1763) created another issue because it doesn't respect preserveState and reuses page components even when preserveState is set to false. This PR fixes this issue.
I have updated the Svelte playground with a reproducible to help me find a solution and also help the reviewer. We can revert these changes to the playground before merging this PR.
Before
Navigating between /foo and /bar, which use the same page component, doesn't refresh the page component, but only updates its props. The same page component is reused instead of being destroyed and a new one being mounted.
After
Navigating between /foo and /bar will use a fresh instance of the page component each time, see the "mounted" and "destroyed" logs.
This PR still doesn't fully solve the issue described in #1670. Notice on the blue arrows on the "After" screenshot that in some cases the component prop is updated shortly after the component is initialized. In my tests, this only happened when I tried to use a prop inside the <script> block. Using props in reactive expressions and lifecycle hooks such as onMount works just fine.
<script>
import { useForm } from '@inertiajs/svelte'
export let name
const form = useForm({
'name': name,
})
</script>
After a lot of debugging, I found out that this happens because we are using a Svelte store to persist component and props state. When the store is updated their listeners can be slightly out-of-sync. This causes the internal <App /> component to pass outdated props down to the component tree.
I have a working solution and will open a separate PR to fix that because there might be a small breaking change.