For is not Reactive ?

Hi, I've made this filter list using For:
<ul
tabIndex={0}
class={`dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52`}
>
<For each={filters()}>
{(f) => (
<li>
<div
onClick={() => toggleFilter(f.id)}
class="flex justify-between"
>
<p>{f.label}</p>
{f.selected ? <FaSolidCheck size={12} /> : null}
</div>
</li>
)}
</For>
</ul>
<ul
tabIndex={0}
class={`dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52`}
>
<For each={filters()}>
{(f) => (
<li>
<div
onClick={() => toggleFilter(f.id)}
class="flex justify-between"
>
<p>{f.label}</p>
{f.selected ? <FaSolidCheck size={12} /> : null}
</div>
</li>
)}
</For>
</ul>
The signal looks like this:
const [filters, setFilters] = createSignal([
{ id: 'active', label: 'Active', selected: true },
{ id: 'terminated', label: 'Terminated', selected: false },
]);

const toggleFilter = (id: string) => {
console.log('before', filters()[0].selected);

setFilters(
filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}

return f;
}),
);

console.log('after', filters()[0].selected);
};
const [filters, setFilters] = createSignal([
{ id: 'active', label: 'Active', selected: true },
{ id: 'terminated', label: 'Terminated', selected: false },
]);

const toggleFilter = (id: string) => {
console.log('before', filters()[0].selected);

setFilters(
filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}

return f;
}),
);

console.log('after', filters()[0].selected);
};
The console logs show that the value are changing, but the elements are not re-rendering. Am I missing something ?
10 Replies
Jasmin 🌈💜
Jasmin 🌈💜5mo ago
You mutate the array, which doesn't trigger observers. You need to create a new array when setting the signal. This works:
setFilters(
[...filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}
return f;
})]
);
setFilters(
[...filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}
return f;
})]
);
Cyber Grandma
Cyber Grandma5mo ago
Thanks, I thought it was something like that. But this was an exemple from the docs so I trusted it.
Jasmin 🌈💜
Jasmin 🌈💜5mo ago
oh really thinkies can you share the link?
Cyber Grandma
Cyber Grandma5mo ago
I'll have to find that Was 3 days ago ^^' @Jasmin It still isn't updating the HTML 🥺 Damn it makes me feel super dumb
Jasmin 🌈💜
Jasmin 🌈💜5mo ago
ohh you're editing an object. You need to recreate that too
Cyber Grandma
Cyber Grandma5mo ago
<For each={filters()}>
{(f) => {
console.log('render');

return (
<li>
<div
onClick={() => toggleFilter(f.id)}
class="flex justify-between"
>
<p>{f.label}</p>
{f.selected ? <FaSolidCheck size={12} /> : null}
</div>
</li>
);
}}
</For>
<For each={filters()}>
{(f) => {
console.log('render');

return (
<li>
<div
onClick={() => toggleFilter(f.id)}
class="flex justify-between"
>
<p>{f.label}</p>
{f.selected ? <FaSolidCheck size={12} /> : null}
</div>
</li>
);
}}
</For>
const toggleFilter = (id: string) => {
setFilters([
...filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}

return f;
}),
]);
};

createEffect(() => {
console.log('filters', filters());
});
const toggleFilter = (id: string) => {
setFilters([
...filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}

return f;
}),
]);
};

createEffect(() => {
console.log('filters', filters());
});
The effect is triggering tho
Jasmin 🌈💜
Jasmin 🌈💜5mo ago
setFilters(
[...filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}
return Object.assign({}, f);
})]
);
setFilters(
[...filters().map((f) => {
if (f.id === id) {
f.selected = !f.selected;
}
return Object.assign({}, f);
})]
);
yes because you are listening to f.selected and that isn't reactive if f, the object doesn't change
Jasmin 🌈💜
Jasmin 🌈💜5mo ago
but for your usecase, a store probably fits better: https://www.solidjs.com/docs/latest/api#using-stores
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
Cyber Grandma
Cyber Grandma5mo ago
Thanks It's really appreciated ❤️ I will try this out, have a great day
Jasmin 🌈💜
Jasmin 🌈💜5mo ago
you're welcome! And thanks, you too! :)