svelte - Statement rerun unnecessarily - Stack Overflow

I have some strange things happening on my svelte code, here are the simplified version of my codeREPL

I have some strange things happening on my svelte code, here are the simplified version of my code

REPL:

+page.svelte

<script lang="ts">
  import { writable } from 'svelte/store'

  import Provider from './provider.svelte'

  import Test from './test.svelte'

  const sdk = writable<object>({})
  sdk.subscribe((v) => console.log('sdk updated:', v))
</script>

<div class="w-full mx-auto max-w-xl">
  <h2 class="text-center text-gray-30 uppercase text-c2">Transfer</h2>
  <Provider let:values let:val>
    <form class="flex flex-col gap-4">
      <button
        on:click={() => {
          console.log('update balance')
          values.update((v) => {
            return { ...v, balance: 0 }
          })
        }}>update balance</button>
      <button
        on:click={() => {
          sdk.set({})
        }}>update sdk</button>
      <Test
        func={async () => {
          await new Promise((resolve) => setTimeout(resolve, 1500))
          console.log('update balance')
          values.update((v) => {
            return { ...v, balance: 0 }
          })
        }}
        sdk={$sdk} />
    </form>
  </Provider>
</div>

provider.svelte

<script lang="ts">
  import { writable } from 'svelte/store'

  const values = writable({})
</script>

<slot {values} val={$values} />

test.svelte

<script lang="ts">
  import { onDestroy } from 'svelte'

  export let sdk: any
  export let func: () => Promise<any>
  $: console.log('sdk TEST!', sdk)
  $: {
    if (sdk) {
      func()
    }
  }

  onDestroy(() => {
    console.log('destroyed')
  })
</script>

Can anyone tell me why when I click on the update sdk button, the calls flow:

  1. sdk updated
  2. sdk TEST!
  3. update balance
  4. sdk TEST!
  5. update balance ...

it is weird because the sdk TEST! is getting called after the update balance, because in update balance, there is no change to sdk, even the sdk updated is not getting called.

when I try to call the update balance using the other button (update balance button), it doesn't call the sdk TEST! after the balance update

so why the update balance call from the func makes sdk TEST! getting called, why the update balance from the button doesn't?

I have some strange things happening on my svelte code, here are the simplified version of my code

REPL: https://codesandbox.io/p/devbox/hcfk3l

+page.svelte

<script lang="ts">
  import { writable } from 'svelte/store'

  import Provider from './provider.svelte'

  import Test from './test.svelte'

  const sdk = writable<object>({})
  sdk.subscribe((v) => console.log('sdk updated:', v))
</script>

<div class="w-full mx-auto max-w-xl">
  <h2 class="text-center text-gray-30 uppercase text-c2">Transfer</h2>
  <Provider let:values let:val>
    <form class="flex flex-col gap-4">
      <button
        on:click={() => {
          console.log('update balance')
          values.update((v) => {
            return { ...v, balance: 0 }
          })
        }}>update balance</button>
      <button
        on:click={() => {
          sdk.set({})
        }}>update sdk</button>
      <Test
        func={async () => {
          await new Promise((resolve) => setTimeout(resolve, 1500))
          console.log('update balance')
          values.update((v) => {
            return { ...v, balance: 0 }
          })
        }}
        sdk={$sdk} />
    </form>
  </Provider>
</div>

provider.svelte

<script lang="ts">
  import { writable } from 'svelte/store'

  const values = writable({})
</script>

<slot {values} val={$values} />

test.svelte

<script lang="ts">
  import { onDestroy } from 'svelte'

  export let sdk: any
  export let func: () => Promise<any>
  $: console.log('sdk TEST!', sdk)
  $: {
    if (sdk) {
      func()
    }
  }

  onDestroy(() => {
    console.log('destroyed')
  })
</script>

Can anyone tell me why when I click on the update sdk button, the calls flow:

  1. sdk updated
  2. sdk TEST!
  3. update balance
  4. sdk TEST!
  5. update balance ...

it is weird because the sdk TEST! is getting called after the update balance, because in update balance, there is no change to sdk, even the sdk updated is not getting called.

when I try to call the update balance using the other button (update balance button), it doesn't call the sdk TEST! after the balance update

so why the update balance call from the func makes sdk TEST! getting called, why the update balance from the button doesn't?

Share Improve this question edited Nov 28, 2024 at 18:32 Teodorus Nathaniel asked Nov 18, 2024 at 18:46 Teodorus NathanielTeodorus Nathaniel 1126 bronze badges 4
  • Your case is not reproducible. In the REPL, I see: sdk updated, sdk TEST!, update balance (from the timer), and then when the button is clicked, an extra update balance. That's it. – José Ramírez Commented Nov 20, 2024 at 4:49
  • I tried this and its reproducible for me, I create new sveltekit repo by using npx sv create my-app and change the svelte version to ^4.2.7 and @sveltejs/vite-plugin-svelte version to ^3.0.0 – Teodorus Nathaniel Commented Nov 28, 2024 at 5:05
  • Then please provide the REPL yourself. – José Ramírez Commented Nov 28, 2024 at 13:36
  • Updated my question, added the REPL using codesandbox – Teodorus Nathaniel Commented Nov 28, 2024 at 18:33
Add a comment  | 

1 Answer 1

Reset to default 1

And round and round it goes xD It's a bit hard for me to follow the code execution in my head, but I think the problem is the func prop in the <Test> component. When the function in the func prop is called, then you change the values store, and I that causes the <Provider> child to re-render, because in the <Provider> component you pass its children the prop val={$values}. So, when values is a assigned a new value:

  1. The <Provider> component will re-render its child
  2. That child will re-render <Test func={...} />
  3. When <Test> is re-rendered, it will change the value in values
  4. Which causes a re-render of (1), and in the merry-go-round we are! :D

I think you can solve the problem by simply skipping the val prop in the provider.svelte component. That's the one that causes an unnecessary re-rendering, because you don't use it anyway.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745600882a4635393.html

相关推荐

  • svelte - Statement rerun unnecessarily - Stack Overflow

    I have some strange things happening on my svelte code, here are the simplified version of my codeREPL

    13小时前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信