S
SolidJS2mo ago
Willi

Struggling with Router useParams() reactivity

Hello People! I'm loving SolidJS, and I am working on a little "garden" like project, where I can write notes in MDX and have it all work without ever compiling anything. I have an index.html page, that uses solid-js to render the MDX files client side. This does work very nicely. But while switching routes in the url bar of the browser, the site doesn't reload. So, going from localhost:8000/index.html/#/test.mdx to localhost:8000/index.html/#/test2.mdx doesn't work, unless I manually refresh the browser. I tried multiple different approaches with createResource, createEffect, and createMemo, but I am not knowledgeable enough to know what the correct approach is. I currently think this is a Usage Issue, not a Bug, that is why I decided to ask on Discord. Any help would be appreciated! Have a nice day everyone.
<!DOCTYPE html>
<html>
<body>
<script type="module">
// I had to remove the import statements because of Discord char limit

const baseUrl = "http://localhost:8000";

const RouteRenderer = (props) => {

const params = useParams();

const [mdxc] = createResource(params, async (p) => {
const response = await fetch("/" + p.path);
const filecontent = await response.text();
const { default: MDXContent } = await evaluate(
filecontent,
{ ...runtime,
baseUrl: baseUrl,
jsxImportSource: 'https://esm.sh/solid-js@1.8.1/h/',
remarkPlugins: [[remarkGfm, remarkMath]] }
);
return MDXContent;
});

return h("div", () => mdxc())
};

const App = () => {
return h(HashRouter, {}, h(Route, { path:"/*path", component: RouteRenderer }));
};

render(App, document.body);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<script type="module">
// I had to remove the import statements because of Discord char limit

const baseUrl = "http://localhost:8000";

const RouteRenderer = (props) => {

const params = useParams();

const [mdxc] = createResource(params, async (p) => {
const response = await fetch("/" + p.path);
const filecontent = await response.text();
const { default: MDXContent } = await evaluate(
filecontent,
{ ...runtime,
baseUrl: baseUrl,
jsxImportSource: 'https://esm.sh/solid-js@1.8.1/h/',
remarkPlugins: [[remarkGfm, remarkMath]] }
);
return MDXContent;
});

return h("div", () => mdxc())
};

const App = () => {
return h(HashRouter, {}, h(Route, { path:"/*path", component: RouteRenderer }));
};

render(App, document.body);
</script>
</body>
</html>
11 Replies
Willi
Willi2mo ago
import { render } from "https://esm.sh/solid-js@1.8.1/web";
import { HashRouter, Route, useParams } from "https://esm.sh/@solidjs/router";
import h from "https://esm.sh/solid-js@1.8.1/h";
import { createResource, createEffect } from "https://esm.sh/solid-js@1.8.1";
import remarkGfm from "https://esm.sh/remark-gfm@4?bundle";
import remarkMath from "https://esm.sh/remark-math@6?bundle";
import { evaluate } from "https://esm.sh/@mdx-js/mdx@3?bundle";
import * as runtime from 'https://esm.sh/solid-js@1.8.1/h/jsx-runtime';
import { render } from "https://esm.sh/solid-js@1.8.1/web";
import { HashRouter, Route, useParams } from "https://esm.sh/@solidjs/router";
import h from "https://esm.sh/solid-js@1.8.1/h";
import { createResource, createEffect } from "https://esm.sh/solid-js@1.8.1";
import remarkGfm from "https://esm.sh/remark-gfm@4?bundle";
import remarkMath from "https://esm.sh/remark-math@6?bundle";
import { evaluate } from "https://esm.sh/@mdx-js/mdx@3?bundle";
import * as runtime from 'https://esm.sh/solid-js@1.8.1/h/jsx-runtime';
Here are the missing imports!
Brendonovich
Brendonovich2mo ago
the issue is you're passing params as a whole as the source for createResource. you need to instead pass a function that reads all the params you care about:
createResource(
() => params.path,
(path) => ...
)
createResource(
() => params.path,
(path) => ...
)
createResource will only call the provided source for you, it won't read keys of objects. gotta do that inside a signal wait am i silly nope nvm
Willi
Willi2mo ago
const [mdxc] = createResource(() => params.path, async (path) => {
const response = await fetch("/" + path);
const [mdxc] = createResource(() => params.path, async (path) => {
const response = await fetch("/" + path);
Thanks for the suggestion! I changed the code based on it like this, but It still does not change the behaviour. What do you mean by me needing to use a signal? No worries :D
Brendonovich
Brendonovich2mo ago
accessing params.path inside that little function effectively turns that function into a signal, since reading it inside an effect will subscribe the effect to the values read inside it out of curiosity what happens if you log mdxc in a createEffect?
Willi
Willi2mo ago
function MDXContent(props)
length: 0
name: "MDXContent"
prototype: Object { … }
prototype>: function ()
function MDXContent(props)
length: 0
name: "MDXContent"
prototype: Object { … }
prototype>: function ()
I got two log messages, one undefined, and then this output. Oh, so wrapping the read in an arrow function turns it into a signal? Interesting, thx
Brendonovich
Brendonovich2mo ago
hmm you don't get a third message when the path changes?
Willi
Willi2mo ago
Didn't actually try that, whoops. But I did now, and no, url changes do not invoke another log
Brendonovich
Brendonovich2mo ago
Oh, so wrapping the read in an arrow function turns it into a signal?
basically yea, though you could alternatively imagine copy pasting the body of the function directly into an effect so that it tracks it hm that's really strange then my suspicion is that it's a HashRouter bug but i have no qualification to say that haha
Willi
Willi2mo ago
Alright, I'm gonna wait a bit for other people on discord, and maybe file an issue on the repo and see what people have to say there. But thank you so much for your time mate!
mdynnl
mdynnl2mo ago
generally, it’s likely a mismatched solid js version if the code looks okay and the reactivity doesn’t work and that’s actually the case here check what https://esm.sh/@solidjs/router imports
Willi
Willi2mo ago
Oh man, you are absolutely correct! That was the issue, the versions didn't match. I switched from 1.8.1 to 1.8.15 and pinned the router to 0.13.1
https://esm.sh/@solidjs/router@0.13.1
https://esm.sh/@solidjs/router@0.13.1
Thanks for the help