SolidJSS
SolidJS17mo ago
J

Mutate a Resource after fetch efficiently when using <For>

Here's some "pseudo"code:
const [files, { refetch, mutate }]: Resource<File[] | undefined> = createResource(async () =>
   await retrieveFiles(/* some path */)
);

// ...

async function onFileCreated(path: string) {
    mutate([
        ...files,
        ...(await getFileMetadata(path)),
    ]);
}

// In a component:
<For each={files()!}>
   // Omitted
</For>


Now this works, however, anytime a file is created and mutate is called,
For
does not do any diffing and just goes through the arduous process of re-initializing every single DOM element it had already rendered.

I have messed around with using this setup based off this Reddit thread from 2 years:
import { createDeepSignal } from "@solid-primitives/resource";

const [files, { refetch, mutate }] = createResource(async () =>
   await retrieveFiles(/* some path */),
   {
       storage: createDeepSignal
   }
);

but to no avail. Whenever I call mutate my entire list which was rendered by
<For>
simply disappears. I honestly do not really understand what in the world createDeepSignal is supposed to do. The API seems extremely archaic.

TLDR: I need a reactive resource that I can update with mutate, but that still has SolidJS's
<For>
diffing so the entire list isn't re-rendered when just one new item is added to the array.

Also on a side note, can I pass multiple signals as a source to
createResource
? Based off the typedef (
export type ResourceSource<S> = S | false | null | undefined | (() => S | false | null | undefined);
) it would seem not, but that seems like a major oversight to me, is there seriously no way to pass an array of Accessors or something like that??
Was this page helpful?