I have 3 questions regarding Svelte Stores:
//store.js
import { writable } from 'svelte/store';
let data = [];
const apiURL = "https://jsonplaceholder.typicode.com/todos";
async function getData(){
const response = await fetch(apiURL);
data = (await response.json()).slice(0,20);
console.log('Response:', data);
}
getData();
export const testsStore = writable(data);
The request goes trough but the data never gets passed to the export. All the examples I've seen use static data without async/await. I've also tried return data;
and writable(getData());
but it return a promise and not the data itself.
Is this even the right way of loading data from API into a store or should I make the call somewhere else.
How and when do I use export default testsStore;
I tried using it from another example and it throws saying that store.js isn't exporting testsStore
Since it's a writable store, you can call set
or update
on it to change the data (see docs).
For example:
import { writable } from 'svelte/store';
const apiURL = "https://jsonplaceholder.typicode.com/todos";
async function getData(){
const response = await fetch(apiURL);
const data = (await response.json()).slice(0,20);
testStore.set(data) // <================================
}
getData();
export const testStore = writable([])
However, it seems that this specific use case would be better served by a readable store. A readable store takes its initial value as first argument and a "lifecycle" function as its second argument. The lifecyle function receives a set
function to change the store value, but the store itself doesn't expose set
or update
methods (hence it's not writable from the outside).
For example:
import { readable } from 'svelte/store';
const apiURL = "https://jsonplaceholder.typicode.com/todos";
const getData = async () => {
const res = await fetch(apiURL)
if (!res.ok) throw new Error('Bad response')
const items = await res.json()
return items.slice(0, 20)
}
export const todos = readable([], set => {
// called when the store is first subscribed (when subscribers goes from 0 to 1)
getData()
.then(set)
.catch(err => {
console.error('Failed to fetch', err)
})
return () => {
// you can do cleanup here if needed
}
})
Finally, in .svelte
components, you can prefix stores with a $
to directly access their value. With this notation, Svelte will automatically subscribe to the store when needed, and unsubscribe from it when the component is destroyed.
So in your example, using our readable todos
store above, you can change your component to simply this:
<script>
import { todos } from './store.js';
</script>
<h1>Todos:</h1>
{#each $todos as item}
<p>{item.title}</p>
{/each}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With