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:
- sdk updated
- sdk TEST!
- update balance
- sdk TEST!
- 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:
- sdk updated
- sdk TEST!
- update balance
- sdk TEST!
- 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?
1 Answer
Reset to default 1And 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:
- The
<Provider>
component will re-render its child - That child will re-render
<Test func={...} />
- When
<Test>
is re-rendered, it will change the value invalues
- 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
npx sv create my-app
and change thesvelte
version to^4.2.7
and@sveltejs/vite-plugin-svelte
version to^3.0.0
– Teodorus Nathaniel Commented Nov 28, 2024 at 5:05