Skip to content

[Svelte 5] Can't modify data prop #9905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
PP-Tom opened this issue Dec 13, 2023 · 8 comments
Closed

[Svelte 5] Can't modify data prop #9905

PP-Tom opened this issue Dec 13, 2023 · 8 comments
Milestone

Comments

@PP-Tom
Copy link

PP-Tom commented Dec 13, 2023

Describe the bug

This is useful for the CMS StoryBlok where it has a visual editor, it does this by updating the data json as you type. In Svelte 4 we can reassign this to the data attribute so the UI updates, in Svelte 5 this isn't possible. You can however use $state(data) to allow updates but in terms of backwards compatibility it might be useful to allow it.

Reproduction

Svelte 4: https://stackblitz.com/edit/sveltejs-kit-template-default-uwn6wh?file=src%2Froutes%2F%2Bpage.svelte
Svelte 5: https://stackblitz.com/edit/sveltejs-kit-template-default-6nqofs?file=src%2Froutes%2F%2Bpage.svelte

Logs

`Uncaught Error: Non-bound props cannot be mutated — use `bind:<prop>={...}` to make `count` settable. Fallback values can never be mutated.`

System Info

StackBlitz

Severity

blocking all usage of svelte

EDIT:
Thinking on all the projects that would require a decent sized refactor because of this, it would make me avoid updating to Svelte 5 for those projects. I've updated Severity to blocking upgrade due to this.

@Malix-Labs
Copy link

Malix-Labs commented Dec 30, 2023

I think that is desired, so not a bug but a feature

If that is true, would that issue be a feature request to allow non-bound props to be mutated?
If yes, it should be deleted and created under the appropriate issue template

Not sure though

Update

Apparently, it indeed does seem like a bug 🐛

@PP-Tom
Copy link
Author

PP-Tom commented Jan 1, 2024

@Malix-off, what is the reasoning for the change? As far as I'm aware Rich was wanting backwards compatibility with Svelte 4 and this would break 90% of my projects on update and require some refactoring. It will also break most people's StoryBlok setup with Svelte I should imagine (https://www.storyblok.com/tp/add-a-headless-cms-to-svelte-in-5-minutes#listening-to-changes-in-the-visual-editor).

@Thiagolino8
Copy link

It looks like a bug to me
especially because modifying the prop data is currently the way to make optimistic updates
https://youtu.be/HdkJTOTY-Js?t=663

@PP-Tom
Copy link
Author

PP-Tom commented Jan 3, 2024

I've updated to blocking all usage of svelte, this has become critical for me. When dealing with routes for example [slug]/+page.svelte, data.story updates when changing routes which is correct, however, I need to update data.story for StoryBlok's live editor work, so to do this I wrap data.story in a $state as I can't directly mutate data.story. I found that changing between pages in the same route causes $state to stay the same as it doesn't detect the update of page. Makes completely sense, it needs to be $derived however, I can not reassign a $derived value for live update.

Currently this completely breaks StoryBlok with Svelte.

@dummdidumm
Copy link
Member

Can you give an example how this breaks StoryBlok with Svelte? In which way do you interact with StoryBlok and mutate its state so that it currently breaks?

dummdidumm added a commit to sveltejs/kit that referenced this issue Feb 6, 2024
By doing `bind:data/form`, the layout/child components are allowed to mutate those properties
Related sveltejs/svelte#9905
@dummdidumm
Copy link
Member

Since #10464 this will only be a warning and not an error anymore.

@MarkusWendorf
Copy link

@dummdidumm I think @PP-Tom meant the code from the Storyblok documentation (here Section: "Listening to changes in the Visual Editor"):

<script>
  import { onMount } from "svelte";
  import { useStoryblokBridge, StoryblokComponent } from "@storyblok/svelte";

  export let data;

  onMount(() => {
      useStoryblokBridge(
          data.story.id,
          // modifying data here
          (newStory) => (data.story = newStory)
      );
  });
</script>

<div>
  {#if data.story}
      <StoryblokComponent blok={data.story.content} />
  {/if}
</div>

But I think one could just put the story data into state?

@dummdidumm
Copy link
Member

Yeah looks like it. The other alternative would be to use reassignment (data = { ...data, story: newStory }) rather than mutation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants