S
SolidJS14mo ago
Merlin

Refetching Route Data with Solid Router

Is there any way to refetch (revalidate) the data functions with @solidjs/router? (not Solid Start; I'm using Vite) - I'm mutating something on the backend and would like to make sure the data is up to date - Returning the whole createResource return value kind of works -- calling refetch correctly refetches the data, but mutate doesn't work. - Additionally, I'd like to refetch/revalidate all resources somehow. Is that possible?
68 Replies
Jules
Jules14mo ago
Happy to take a look, what do you mean by mutate doesn't work? Also posting some code would be helpful for us to lend a hand
Merlin
Merlin14mo ago
// --- App.tsx ---

const Project = lazy(() => import("./pages/dashboard/Project"));
const getProjectData = ({ params }) => createResource(() => fetch(...));

<Routes>
<Route
path="/project/:id"
component={Project}
data={getProjectData}
/>
</Routes>


// --- Project.tsx ---

function Project() {
// SolidJS docs recommend returning createResource()[0]
// so I wouldn't have access to refetch() if going by the docs.
//
// ...then how do I refresh?
const [project, { refetch, mutate }] = useRouteData();

function someCallback() {
// This should trigger an update of the `project` signal immediately,
// since mutate is a signal setter, but it doesn't!
//
// The data itself gets updated -- when components rerender, the new values are shown.
// So this is a reactivity issue.
mutate({ title: "foobarbaz" });
}

return <div>{project().title}</div> // mutate() will not trigger a DOM update here
}
// --- App.tsx ---

const Project = lazy(() => import("./pages/dashboard/Project"));
const getProjectData = ({ params }) => createResource(() => fetch(...));

<Routes>
<Route
path="/project/:id"
component={Project}
data={getProjectData}
/>
</Routes>


// --- Project.tsx ---

function Project() {
// SolidJS docs recommend returning createResource()[0]
// so I wouldn't have access to refetch() if going by the docs.
//
// ...then how do I refresh?
const [project, { refetch, mutate }] = useRouteData();

function someCallback() {
// This should trigger an update of the `project` signal immediately,
// since mutate is a signal setter, but it doesn't!
//
// The data itself gets updated -- when components rerender, the new values are shown.
// So this is a reactivity issue.
mutate({ title: "foobarbaz" });
}

return <div>{project().title}</div> // mutate() will not trigger a DOM update here
}
Example with comments explaining the problems ☝️ I'm probably just doing something dumb (or this isn't supported at all)
Jules
Jules14mo ago
No, no the solid docs are a work in progress I afaik so a lot of things aren't well documented but are fully supported. So when you call mutate you expect it to mutate the resource object, but are you also mutating it on the server so that if it refetches the new data would be the same as the "feebarbaz" object? Oh I see, interesting, I just read the comments and you're saying the data in project object is updated as per the call to the setter but it doesn't cause a rerender despite using them in a reactive context i.e calling the getter? So the way I normally go about this is: - someCallback realizes that the data needs to be updated and sends a tRPC call to the backend with the new object, then I trigger a refetch of the async data so I don't have to mutate my values at all, you can do optimistic updates by using the mutate function and then reconciling with the servers response, does this sound like what your implementation is?
Jules
Jules14mo ago
https://start.solidjs.com/api/useRouteData#retrieving-data-from-the-routedata-function you can't blame yourself for not knowing how this works, the docs are pretty sparse on the setter and getters
SolidStart Beta Documentation
SolidStart Beta Documentation
Early release documentation and resources for SolidStart Beta
Merlin
Merlin14mo ago
Yes! Exactly
Jules
Jules14mo ago
That is certainly very strange
Merlin
Merlin14mo ago
you can do optimistic updates by using the mutate function
Exactly what I'm trying to do refetching works, but if the user has a slow connection, it comes out all janky
Jules
Jules14mo ago
Right okay cool, so we're on the same page. What do you mean by janky? like I know it means not great lol
Merlin
Merlin14mo ago
Oh I just meant the user experience lmao
Jules
Jules14mo ago
gotcha Like flickering and layout shift?
Merlin
Merlin14mo ago
Yeah
Merlin
Merlin14mo ago
This isn't the codebase I'm working on right now, but take a look at this:
Merlin
Merlin14mo ago
After unfocusing the input, there's a 1-2s delay until it's done refetching I want to optimistically update, but mutate doesn't seem to work But I may be doing something stupid, I'll definitely try again to make sure It's weird because refetch works, though Is there any possibility this isn't related to mutate, but to list rendering? The stuff I'm trying to mutate is an array rendered by <For> So my mutate call ends up looking like this:
const idToUpdate = 123;

const upd = projects(); // route data resource getter

// array copy alternative that doesn't work either:
// const upd = [...projects()];

upd.find(p => p.id === idToUpdate)?.title = "some new title";

mutate(upd);
const idToUpdate = 123;

const upd = projects(); // route data resource getter

// array copy alternative that doesn't work either:
// const upd = [...projects()];

upd.find(p => p.id === idToUpdate)?.title = "some new title";

mutate(upd);
Jules
Jules14mo ago
Oh totally get the problem, but I haven't yet attempted this in solid, I am rewriting my Next.js and React app in Solid and I managed to do it in two nights, plus some finagling - which coincidentally, leaves me with one more job to do, update a users profile optimistically using Solid's createResource, so I am in the same boat as you
Merlin
Merlin14mo ago
oh lol
Want results from more Discord servers?
Add your server