Using Router with ssr and hydrate, click event not working
Closed this issue · 1 comments
Describe the bug
I have set up a simple TypeScript solidjs.
The application generates ssr and hydrate files.
When I do not use Router the click event works but when using Router the click event does not work.
I put the full sample project at https://stackblitz.com/edit/stackblitz-starters-5rgwrj?file=package.json
Am I missing a config on Router?
Please note this is a sample that I got the part not working, my project makes use of <A>
etc.
Layout.tsx
`import type { Component } from 'solid-js';
const Layout: Component = (props: any) => {
const showAlert = () => {
console.log('Alert button clicked!'); // Debugging log
alert('Button clicked!');
};
return (
<>
click me from layout
{props.children}
</>
);
};
export default Layout;
`
App.tsx
`
import type { Component } from 'solid-js';
const App: Component = () => {
const showAlert = () => {
console.log('Alert button clicked!'); // Debugging log
alert('Button clicked!');
};
return (
click me
);
};
export default App;
index.tsx
/* @refresh reload */
import { hydrate } from 'solid-js/web';
import { Router } from '@solidjs/router';
import Layout from './Layout';
import App from './App';
const root = document.getElementById('root');
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
throw new Error(
'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?'
);
}
const routes = {
path: '/',
component: App,
};
// works
// hydrate(() => , root!);
// does not work
hydrate(
() => (
{routes}
),
root!
);
`
index_server.tsx
`/* @refresh reload */
import { generateHydrationScript, renderToStringAsync } from 'solid-js/web';
import { Router } from '@solidjs/router';
import App from './App';
import Layout from './Layout';
const routes = {
path: '/',
component: App,
};
export default async function render() {
//work
//const rendered = await renderToStringAsync(() => );
// does not work
const rendered = await renderToStringAsync(() => (
{routes}
));
const hydration = generateHydrationScript();
return [rendered, hydration];
}
vite.config.ts
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
// import devtools from 'solid-devtools/vite';
export default defineConfig(({ command, mode }) => {
const isSSR = mode == "ssr";
return {
plugins: [
/*
Uncomment the following line to enable solid-devtools.
For more info see https://github.com/thetarnav/solid-devtools/tree/main/packages/extension#readme
*/
// devtools(),
solidPlugin({
solid: {
generate: isSSR ? 'ssr' : 'dom', // Conditionally set generate based on SSR build
},
}),
],
server: {
port: 3000,
},
build: {
target: 'esnext',
ssr: isSSR,
rollupOptions: {
input: isSSR
? src/index_server.tsx
: src/index.tsx
,
output: {
format: 'esm', // Output format differs for server and client
entryFileNames: isSSR ? 'server.js' : 'client.js',
assetFileNames: (assetInfo) => {
// by default it comes with a random hash... this was removed by removign -[hash] field
//return 'assets/[name]-[hash][extname]';
return 'assets/[name][extname]';
}
},
},
outDir: isSSR ? dist/server
: dist/client
},
}});
package.json
{
"name": "vite-template-solid",
"version": "0.0.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build && vite build --mode ssr ",
"serve": "vite preview"
},
"license": "MIT",
"devDependencies": {
"solid-devtools": "^0.29.2",
"typescript": "^5.3.3",
"vite": "^5.0.11",
"vite-plugin-solid": "^2.8.2"
},
"dependencies": {
"@solidjs/router": "^0.14.3",
"express": "^4.19.2",
"solid-js": "^1.8.11"
},
"type": "module"
}
`
the following command i use to generate both client.js and server.js: npm run build
server.js to host
`
import express from "express";
const app = express();
app.use(express.static('dist'));
app.use(express.json());
app.get('/*', async (req, res) => {
const renderFunc = (await import(./dist/server/server.js
)).default;
const [html, script] = await renderFunc();
const output = <!DOCTYPE html> <html> <head> <title>SSR with SolidJS</title> <link rel="shortcut icon" href="/templates/backoffice/app/assets/favicon.png"> </head> <body> <div id="root">${html}</div>${script}<script type="module" src="/client/client.js"></script> </body> </html>
;
res.send(output);
});
var port = 9001;
app.listen(port, () => {
console.log('ready');
console.log("http://localhost:" + port);
});
`
Your Example Website or App
https://stackblitz.com/edit/stackblitz-starters-5rgwrj?file=package.json
Steps to Reproduce the Bug or Issue
If you run the server node server.js, the opened pages will show "click me" button and does not work.
If you change the content in index.tsx and index_server.tsx to use App component directly and npm run build to build the js files then node server.js to host the application, the "click me" button will work
Expected behavior
"click me" button shows an alert when using Router
Screenshots or Videos
No response
Platform
- OS: Windows
- Browser: Brave
- Version: 1.69.153
Additional context
No response
for some reason I had to add a <div></div>
instead of empty tag <></>
in the Layout and started working.
from
Layout.tsx
return ( <> <header> <button onclick={showAlert}>click me from layout</button> </header> <main>{props.children}</main> </> );
to
return ( <div> <header> <button onclick={showAlert}>click me from layout</button> </header> <main>{props.children}</main> </div> );
I used <></> because it was in the documentation: https://docs.solidjs.com/solid-router/concepts/layouts