S
SolidJS11mo ago
feusanc

Component doesn't rerender when prop changes

I have the component below:
export default function FolderContents(props: { path: string }) {
const [contents] = createResource(
async () => await fetch_directory(props.path)
);

return stuff
}
export default function FolderContents(props: { path: string }) {
const [contents] = createResource(
async () => await fetch_directory(props.path)
);

return stuff
}
and another component that returns this, but this component doesn't rerender when the given path changes. It reacts to the change in the props, logging it out in the createEffect callback, but it doesn't rerun the createResource part. I was expecting it to rerender completely whenever the given prop changes. How would I solve this? And unfortunately I can't make the path prop a signal, it has to be a string.
7 Replies
feusanc
feusanc11mo ago
export default function FileViewer() {
const path = useStore(pathStore);

return (
<div class="ml-1">
<p>{path()}</p>
<Show when={path()}>
<FolderContents path={path()} />
</Show>
</div>
);
}
export default function FileViewer() {
const path = useStore(pathStore);

return (
<div class="ml-1">
<p>{path()}</p>
<Show when={path()}>
<FolderContents path={path()} />
</Show>
</div>
);
}
and this is one of the components using it the pathStore is an atom store from nanostores
createEffect(() => {
console.log(props.path);
refetch();
});
createEffect(() => {
console.log(props.path);
refetch();
});
with this "trick" I can cause it to refetch and thus rerender, but it only rerenders that depend on the content, I want the whole component to refresh
Tommypop
Tommypop11mo ago
You can just make props.path the source of your resource I think Refreshing the entire component isn't really possible in solid, anything that changes in your component needs to be reactive
createResource(() => props.path, async (path) => {
})
createResource(() => props.path, async (path) => {
})
This will re execute when the path updates
feusanc
feusanc11mo ago
This didnt work either, this was the first thing I tried
Tommypop
Tommypop11mo ago
Can you show the code that didn't work?
feusanc
feusanc11mo ago
The program is having some problems rn, will do in a minute
const [contents] = createResource(props.path, (path) =>
fetch_directory(path)
);

return (
<>
<Switch>
<Match when={contents.loading}>
<div>Loading...</div>
</Match>
<Match when={contents.error}>
<div>Error: {contents.error}</div>
</Match>
<Match when={contents()}>
<For each={contents()}>
{(content) => (
<Switch>
<Match when={content.type === "directory"}>
<Directory file={content} />
</Match>
<Match when={content.type}>
<File file={content} />
</Match>
</Switch>
)}
</For>
</Match>
</Switch>
</>
);
const [contents] = createResource(props.path, (path) =>
fetch_directory(path)
);

return (
<>
<Switch>
<Match when={contents.loading}>
<div>Loading...</div>
</Match>
<Match when={contents.error}>
<div>Error: {contents.error}</div>
</Match>
<Match when={contents()}>
<For each={contents()}>
{(content) => (
<Switch>
<Match when={content.type === "directory"}>
<Directory file={content} />
</Match>
<Match when={content.type}>
<File file={content} />
</Match>
</Switch>
)}
</For>
</Match>
</Switch>
</>
);
ahh I see, I forgot it needs to be an arrow function thank you so much, that solved it
Tommypop
Tommypop11mo ago
Yep, basically it's so that getter is called within the resource so it can be tracked by it
feusanc
feusanc11mo ago
I get it now, thanks