I have following function:
function createProducts(){
/**
* @type {Array.<{
* id: Number,
* name: String,
* product: Array.<{
* id: Number,
* name: String,
* price: Number,
* kitchen: Boolean,
* productCategoryId: Number
* }>
* }>}
*/
let productCategories = $state([])
let allProducts = $derived.by(() => {
let allProducts = []
Object.entries(productCategories).forEach(entry => {
const [key, value] = entry;
console.log(key, value);
allProducts.push(entry.products)
});
return allProducts
})
return {
get productCategories(){
return productCategories
},
set productCategories(newValue){
productCategories = newValue
},
allProducts
}
}
export const products = createProducts()
And this is where the productCategories
are populated:
<script>
import { authorization } from "../store/authorization.svelte";
import Tables from "./Tables.svelte";
import { tables } from "../store/tables.svelte";
import Dialog from "./Dialog.svelte";
import { products } from "../store/products.svelte";
const _token = localStorage.getItem('_token')
$effect(() => {
fetch('http://localhost:9555/api/home', {
method: 'get',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8',
Authorization: `Bearer ${_token}`
}
}
)
.then(resp => resp.json())
.then(json => {
products.productCategories.push(json.productCategories)
})
})
function logout(){
fetch('http://localhost:9555/api/logout', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8',
Authorization: `Bearer ${_token}`
}
}
)
.then(resp => resp.json())
.then(json => {
authorization.logout()
})
}
</script>
When I try to make the list of the products, the products.allProducts
is empty - for some reason the $derived.by is not working, and I can't figure it out why it is not working. What am I doing wrong hjere?
<div id="sidebar">
{#each products.allProducts as product}
{product.name}</span>
{/each}
</div>
Like $state
, derived values have to be closed over, otherwise you just evaluate their current state once and any updates will not be captured:
const allProducts = $dervide.by(...);
return {
// ...
get allProducts() { return allProducts; },
};
Simple standalone example:
<script>
function createCounter() {
let value = $state(1);
const double = $derived(value * 2);
return {
get value() { return value; },
set value(v) { value = v; },
get double() { return double; },
};
}
const counter = createCounter();
</script>
<input bind:value={counter.value} type="number"/>
Double: {counter.double}
In many cases $derived
/$derived.by
only provides value caching and is not strictly necessary for reactivity, so if you do not need caching you can also skip it:
function createCounter() {
const counter = $state({
value: 1,
get double() { return this.value * 2; }
});
return counter;
}