S
SolidJS6mo ago
Xzayler

Mutating a resource

The usecase is that I have comments on a post, and when a new comment is made, I want it to instantly appear on the page without requiring back-end confirmation. My page is set up ina way where I get a post from the server which has a children field which is array of comments. I create a copy of the post object, add the new comment to its children field, and then pass the whole thing to mutate as an arg. However it seems that mutating isn't reactive. The resource value does change (I can test it by console logging) but it doesn't change anything on the page. I have a function like
// inside a component:
const [post, {mutate, refetch}] = createResource(...)

function addCommment(comment: string) {
const p = ...
...
mutate(p)
}

return
<For each={post() ? post()!.children : []}>
{(item) => <Comment comment={item}/>}
</For>
// inside a component:
const [post, {mutate, refetch}] = createResource(...)

function addCommment(comment: string) {
const p = ...
...
mutate(p)
}

return
<For each={post() ? post()!.children : []}>
{(item) => <Comment comment={item}/>}
</For>
It works until first render but when calling the addComment function in another component, the data isn't updated in te html, but it is mutated when I call post() again, like with a console.log.
3 Replies
Maciek50322
Maciek503226mo ago
If in the addComment in places you have the ... ... you do something like that
const p = post();
p.children.push(comment);
mutate(p);
const p = post();
p.children.push(comment);
mutate(p);
then it won't react to this call, because you passed it same reference it already had, so it didn't update things, then you should try
const p = {...post()};
p.children = [...p.children, comment];
mutate(p);
const p = {...post()};
p.children = [...p.children, comment];
mutate(p);
Xzayler
XzaylerOP6mo ago
that is, in fact, exactly what I did. This shows how I still don't really have even the js fundamentals completely down. Thanks for clearing that up, it's working as intended now!
Maciek50322
Maciek503226mo ago
Not really js fundamentals, but solid's. It does equality check when setting new signal's value. If we create signal directly, we can control how the equality check behaves or turn it off (with eg. createSignal(..., { equals: false })). I don't think there's option for this with createResource, so just have to pass different reference. In js {...object} does shallow copy of object, and [...array] shallow copy of array. And while object === object is true, the {...object} === object is false, because they copy and original have different references.
Want results from more Discord servers?
Add your server