-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Implement async function component rendering #4571
Implement async function component rendering #4571
Conversation
Implement async function component rendering. * **src/diff/index.js** - Add async/await support in the `diff` function to handle async function components. - Check if the component returns a Promise and await it in the `diff` function. - Update the `commitRoot` function to handle async components. - Add async/await support in the `diffElementNodes` function. - Add async/await support in the `diffChildren` function. * **src/component.js** - Add async/await support in the `renderComponent` function to handle async function components. - Check if the component returns a Promise and await it in the `renderComponent` function. - Add async/await support in the `process` function to handle async function components. * **src/render.js** - Add async/await support in the `render` function to handle async function components. - Check if the component returns a Promise and await it in the `render` function. - Add async/await support in the `hydrate` function to handle async function components. * **compat/client.js** - Add async/await support in the `render` function to handle async function components. - Check if the component returns a Promise and await it in the `render` function. - Add async/await support in the `hydrateRoot` function to handle async function components. * **compat/client.mjs** - Add async/await support in the `render` function to handle async function components. - Check if the component returns a Promise and await it in the `render` function. - Add async/await support in the `hydrateRoot` function to handle async function components. * **test/browser/asyncFunctionComponent.test.js** - Add tests to ensure async function components render correctly. - Add tests to handle async operations properly in async function components. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/preactjs/preact?shareId=XXXX-XXXX-XXXX-XXXX).
Hey, may I ask what prompted this? Is there something in particular you're after or trying to fix? |
Sure! I was exploring a way to have async components functions in Preact to be able to await blocking functions outside of hooks. I need to implement server side data fetching in a framework I'm building https://github.com/andreafuturi/Singularity I found some solutions online but everything is outdated or not working so I decided to see if I can do something myself with the help of AI. |
Well, a truly async renderer would involve considerably more work than sprinkling Is there a reason why suspense doesn't work for your needs? Suspense, plus |
Yes I could have imagined it would need quite some work, but for sure I wasn't considering it could even influences bundle size. Yes I tried Suspense before with no luck, I might have to try it again. What's this RTS you're talking about? I can seem to find renderToStringAsync only for React |
RTS = render to string; |
Wow thank you! That works now, I have no idea why I have already seen Suspense and lazy documentation but I never noticed there was a renderToStringAsync export in preact-render-to-string. I always used the normal rendertoString function and that for sure was the problem! Thanks again :) |
@andreafuturi do take the pitfalls lined out in #4442 in account when you do suspended hydration |
rtsAsync is fairly new tbf! But you can utilize it for data fetching and the like beyond just I realize our docs are quite lacking here so I'm working on getting some proper SSR demos built next, hopefully it'll help people in the future. Sorry for the inconvenience, we're trying to get better at docs/showing off all the things you can take advantage of. |
Aaah ok I see, no worries at all! I completely understand, thanks for the amazing work 🙏🏻 Keep it up! |
Hi guys does the new signal apis work there? |
This is a very common exception if you search for it in our issues and is mainly caused by duplicate versions of preact in your bundle |
We'd recommend using import maps to solve this for no-build situations: https://preactjs.com/guide/v10/no-build-workflows#preact-with-hooks-signals-and-htm <html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Preact SSR Test</title>
<script type="importmap">
{
"imports": {
"preact": "https://esm.sh/preact@10.23.1",
"preact/": "https://esm.sh/preact@10.23.1/",
"@preact/signals": "https://esm.sh/@preact/signals@1.3.0?external=preact",
"preact-render-to-string": "https://esm.sh/preact-render-to-string?external=preact"
}
}
</script>
</head>
<body>
<noscript>Enable JavaScript to run this example.</noscript>
</body>
</html> import { h } from 'preact';
import { renderToString } from 'preact-render-to-string';
import { useSignal } from '@preact/signals';
// Define a simple component using `useSignal`
function Counter() {
const count = useSignal(20); // Signal created with useSignal
return h('div', null, `Count: ${count.value}`);
}
// Render the component to string asynchronously
(async () => {
// Wrap the component in a fragment or root node
const App = () => h(Counter);
const html = renderToString(h(App));
console.log(html); // Outputs: <div>Count: 20</div>
// Display the rendered HTML in the browser
document.body.innerHTML = `<pre>${html}</pre>`;
})(); Just a note while you're here: |
about the async version of the method, yes I probably changed that while verifying what the problem was exactly and accidentally updated the codepen. For the imports, I already had an importMap in Deno which looked like this:
But I managed to fix the error by aliasing them to npm versions
thank you very much for the hint! :) |
Implement async function component rendering.
src/diff/index.js
diff
function to handle async function components.diff
function.commitRoot
function to handle async components.diffElementNodes
function.diffChildren
function.src/component.js
renderComponent
function to handle async function components.renderComponent
function.process
function to handle async function components.src/render.js
render
function to handle async function components.render
function.hydrate
function to handle async function components.compat/client.js
render
function to handle async function components.render
function.hydrateRoot
function to handle async function components.compat/client.mjs
render
function to handle async function components.render
function.hydrateRoot
function to handle async function components.test/browser/asyncFunctionComponent.test.js
For more details, open the Copilot Workspace session.