S
SolidJS•2y ago
akerbeltz

signal of createResource is not reactive inside a For component

When passing the signal obtained in a request made by createResource and looping the results of that the reactivity when the resource mutate is lost. It works fine if i iterate the signal with a .map() so i don't know what can be the issue.
10 Replies
mdynnl
mdynnl•2y ago
without an example code, it's hard to say though. maybe you're doing along the lines of
mutate(v => {
...
return v
})
mutate(v => {
...
return v
})
then this won't work as the resource's return is just a signal with some getters mashed in if you're returning nested data and wants fine-grained reactivity, createResource with storage : createDeepSignal() backed by createStore might be a good option there's also an implementation of createDeepSignal in solid primitives already
akerbeltz
akerbeltzOP•2y ago
I'm doing this for the signal of the resource
const initialDataDevices = getData('/api/info/devices');
const [devices, { mutate }] = createResource(() => initialDataDevices);
const initialDataDevices = getData('/api/info/devices');
const [devices, { mutate }] = createResource(() => initialDataDevices);
in a create effect i mutate it and using a map the reactivity works and everything works fine
{devices().data.map((device) => ( etc...
{devices().data.map((device) => ( etc...
but if instead of a .map i use <For each{devices()}> it doesn't work
I'll look into the createDeepSignal but it's strange that it works with map and doesn't work with <For> no? How can I get the createResource return that fine-grained reactivity?
mdynnl
mdynnl•2y ago
alright, forget about the fine-grained for a moment For compares individual items by reference and re-run the block only when they differ
mutate(v => {
v[0].foo = 1 // not enough to trigger For, as v[0] is same reference to old v[0]
v[0] = {...v[0]} // this will do as v[0] is a new object

return v.slice() // or [...v] necessary for the signal to change
})
mutate(v => {
v[0].foo = 1 // not enough to trigger For, as v[0] is same reference to old v[0]
v[0] = {...v[0]} // this will do as v[0] is a new object

return v.slice() // or [...v] necessary for the signal to change
})
but deep signal + store's path setter and utilities could helpers could help with this somewhat though
akerbeltz
akerbeltzOP•2y ago
hmm i have this function
createEffect(
on(
message,
(e: string) => {
console.log(JSON.parse(e));
const updateDevices = (devices) => {
let message = JSON.parse(e);
console.log(devices);
let devicesArr = [...devices.data];
const index = devicesArr.findIndex((obj) => obj.id === message.id);
console.log(index);
if (index !== -1) {
devicesArr[index].status = message.status;
}
console.log(devicesArr);
let devicesUpdated = {
...devices,
data: [...devicesArr],
};
console.log(devicesUpdated);
return devicesUpdated;
};
mutate((devices) => updateDevices(devices));
},
{ defer: true }
)
);
createEffect(
on(
message,
(e: string) => {
console.log(JSON.parse(e));
const updateDevices = (devices) => {
let message = JSON.parse(e);
console.log(devices);
let devicesArr = [...devices.data];
const index = devicesArr.findIndex((obj) => obj.id === message.id);
console.log(index);
if (index !== -1) {
devicesArr[index].status = message.status;
}
console.log(devicesArr);
let devicesUpdated = {
...devices,
data: [...devicesArr],
};
console.log(devicesUpdated);
return devicesUpdated;
};
mutate((devices) => updateDevices(devices));
},
{ defer: true }
)
);
I think i'm creating a new object as you said no?
mdynnl
mdynnl•2y ago
maybe a second look will click things for you
akerbeltz
akerbeltzOP•2y ago
as i say this works fine with .map but i imagine this is due to that it renders the whole loop again
mdynnl
mdynnl•2y ago
yeah, i know, that's what For and Index are for
akerbeltz
akerbeltzOP•2y ago
i don't undertand much 😅 how would the code look?
mdynnl
mdynnl•2y ago
devices().data.map.... worked because you returned a new object { ... devices, ...} data is also a new array now but to For, that isn't enough as it also compares the individual items by reference devicesArr[index].status = message.status; here devicesArr[index] is still the same object as before
devicesArr[index] = {...devicesArr[index]} // should fix things
devicesArr[index] = {...devicesArr[index]} // should fix things
akerbeltz
akerbeltzOP•2y ago
now it's more clear. Thanks!
Want results from more Discord servers?
Add your server