Add example of useEffect with dependencies
Closed this issue · 6 comments
Great work with this. Really interesting way for me to learn more about Svelte.
For the useEffect
example, I saw you are only showing a replacement for useEffect with no dependencies for the "onMount" case.
Would be interested in seeing an example for #3 in the readme "With a list of dependency vars: useEffect(fn, [a, b, c]). This reavaulates whenever a dependency changes. Cleans up last value if needed."
Totally agree. I will look into it when I have some more time.
Thanks for opening the issue!
A useEffect
implementation with param can implemented like that
https://dylanvann.com/svelte-version-of-useeffect
There was a discussion about this on twitter, so dropping link here:
https://twitter.com/RyanCarniato/status/1329955721375404032
In Svelte we don't need useEffect
at all. Expression with $:
sign check all dependencies automatically and run only when that dependencies changed. Dependencies here is just variables inside $:
expression. That's why svelte is so awesome
React example
function test() {
const [firstname, setFirstname] = useState('foo')
const [lastname, setLastname] = useState('bar')
const [somethingElse, setSomethingElse] = useState('somethingElse')
useEffect(() => {
console.log(`runs only when firstname: ${firstname} or lastname: ${lastname} changed.`)
}, [firstname, lastname])
return (
<>
<input
type="text"
onInput={(e) => setFirstname(e.target.value)}
placeholder="First name"
/>
<input
type="text"
onInput={(e) => setLastname(e.target.value)}
placeholder="Last name"
/>
<input
type="text"
onInput={(e) => setSomethingElse(e.target.value)}
placeholder="Something else"
/>
</>
)
}
And Svelte example check here. Try to edit text in first and second input and you will see message in the console. But if you try to edit text in third input, you will see nothing in the console because variable binded to third input have not used in the $:
expression
<script>
let firstname = 'foo'
let lastname = 'bar'
let somethingElse = 'somethingElse'
$: {
console.log(`runs only when firstname: ${firstname} or lastname: ${lastname} changed. Because they are used inside this expression`)
}
</script>
<input bind:value={firstname} />
<input bind:value={lastname} />
<input bind:value={somethingElse} />
@osadasami right, if there is no cleanup, then it's just a reactive statement.
if there is cleanup, it could be managed manually
// some external resource
let resource
$: {
// cleanup
if (resource) resource.release()
// subscriber using dependencies
resource = api.subscribe(dep1, dep2, ...)
}
// cleanup when component dismounts
onDestroy(() => { if (resource) resource.cleanup() })
Another alternative is to use a Store
to manage access to the resource.
I think the Svelte way is to avoid resource cleanup at the component level, and instead use stores to turn the resource into reactive state.
Here's an example of a store that wraps an external API, and runs cleanup code when necessary:
import { readable } from 'svelte/store'
import api from './external-resource'
export function resourceStore() {
return readable(null, set => {
const resource = api.getResource()
set(resource.value)
// wire up API
resource.subscribe(value => set(value))
// return a cleanup function
return () => resource.release()
})
}