Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events not working #94

Closed
avishwakarma opened this issue Jun 10, 2019 · 5 comments
Closed

Events not working #94

avishwakarma opened this issue Jun 10, 2019 · 5 comments

Comments

@avishwakarma
Copy link

avishwakarma commented Jun 10, 2019

It seems DOM events are not working when using preact-render-to-string.

import { render } from 'preact-render-to-string';
import {h, Component} from 'preact';

class Page extends Component {
  click(event) {
    console.log(event);
  }

  render(){
    return <button onClick={this.click}>Click me!</button>
  }
}

const html = render(<Page />);

console.log(html);
// <button>Click me!</button>

Preact Version: 8.4.2
PreactRenderToString Version: 4.1.0

@marvinhagemeister
Copy link
Member

This is the correct behaviour. preact-render-to-string turns a virtual DOM tree into a string and a string has by definition no event handlers. That's something only DOM nodes have and those only live inside the browser. If that's what you're trying to do you should use the render() function that's exported from preact itself 👍

@brandonros
Copy link

brandonros commented Aug 10, 2020

https://preactjs.com/guide/v10/api-reference/#hydrate

how is hydrate used?

https://preactjs.com/guide/v10/server-side-rendering/

the official docs recommend this package, but do not describe how to use this package with hydrate to wire up events?

@marvinhagemeister
Copy link
Member

@brandonros Good point we should expand our docs there.

Here is an example that demonstrates how both libraries are used together. Basically the server sends the stringified HTML to the client and the client makes that interactive with hydrate().

// Dummy server:
const http = require('http');
const { h } = require('preact'); 

function App() {
  return <button onClick={() => console.log("click")}>click me</button>
}

const server = http.createServer((req, res) => {
  const app = renderToString(<App />);
  const html = `<!DOCTYPE html>
    <html>
      <body>
        <div id="app">${html}</div>
        <script src="path/to/my-app.js"></script>
      </body>
    </html>`

  res.end(html);

}).listen(3000);

And my-app.js that is shipped to the browser should look something like this:

// Run in the browser
import { h, hydrate } from 'preact';

function App() {
  return <button onClick={() => console.log("click")}>click me</button>
}

// Does (nearly) no diffing, only attaches events
hydrate(<App />, document.getElementById("app"));

@MolikoDeveloper
Copy link

MolikoDeveloper commented Apr 7, 2024

@marvinhagemeister
I am currently working on a project involving bun.serve() and preact SSR (render to string), where I am also exploring the implementation of CSR (Client-Side Rendering) for specific components.

I am encountering some challenges in this endeavor, particularly regarding the integration of a "clientLoad" prop to compile and send dependencies to the static files for client-side loading of events. Despite my efforts, I am still facing difficulties in achieving the desired functionality

// Run in the browser
import { h, hydrate } from 'preact';

function App() {
  return <button onClick={() => console.log("click")}>click me</button>
}

// Does (nearly) no diffing, only attaches events
hydrate(<App />, document.getElementById("app"));

While I appreciate the solutions provided thus far, I have realized that I am not passing any dependencies to the client, which is essential for the loading of preact dependencies. This has led me to explore alternative solutions, but I find myself struggling to simplify the process.

My goal is to avoid serving the entire project to the client and instead focus on executing certain components dedicated to client-side functionality directly on the client.

Attached is the project I am currently experimenting with using preact. Although I am aware that React offers solutions such as "use client," I have reservations about using React due to its heavy nature and the multitude of dependencies it entails.

I am considering modifying Preact and Preact/serverToString slightly to achieve this goal, not with 'use client' as React does. I am not fond of adding arbitrary strings to the code. Instead, I am exploring the possibility of using , similar to what is done in Astro. If successful, I intend to share my progress through a pull request for your review and feedback.

If unsuccessful, there will be no pull request :P

(sorry for the mail format XD, i love your project.)

@marvinhagemeister
Copy link
Member

@MolikoDeveloper That's exciting! You're pretty much describing the Islands architecture on which Astro is also based on to a tee. This approach typically requires the following things:

  1. During SSR rendering, detect when a component is an island and place some form of marker in the HTML. Could be a custom element, could be a start + end comment or something else. Just a way to know that when you're booting up the HTML in the client where the islands are. In Fresh I went with comment markers and used Preact's option-API to detect when a component is an island and when it's not
  2. Create a JS bundle of the islands with a tiny runtime to scan the HTML and make islands interactive. If you've chosen the Custom Elements route you can avoid scanning the HTML step. To make the bundling work you either pass it files that only contain islands, create a virtual entry that only contains islands or do a transpilation pass before hand to do something like the "use client" directive.
  3. Once in the browser your runtime will kick in and hydrate/render the islands to make them interactive again.

The implementation chosen in Fresh to make this work is a little complex, because I went with comment markers and it also supports passing server rendered JSX to islands among a few other features unique to Fresh. Might be worth a look as an inspiration for your project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants