0.4.9 • Published 3 years ago

@saus/react v0.4.9

Weekly downloads
-
License
MIT
Repository
-
Last release
3 years ago

@saus/react

Pre-render your pages with React and @saus/react will generate the module that hydrates your page on the client-side. Use JSX to render your <head> and <body> tags. Use the automatic JSX runtime and Fast Refresh.

Start by importing the render function in your project's src/render.tsx module (or whichever module you set render to in your saus.yaml file).

import { render } from '@saus/react'

Use it to define the default renderer. It receives the loaded module from the page's matching route. You can export whatever you like, but in this example, we're setting the default export to a React component, which represents the page content.

import { render } from '@saus/react'
import React from 'react'

render(module => {
  const Page = module.default as React.ComponentType
  return <Page />
})

Route parameters

If you're using route parameters, you'll want to pass those into your Page component.

import { render } from '@saus/react'
import React from 'react'

render((module, { params }) => {
  const Page = module.default as React.ComponentType
  return <Page {...params} />
})

Routed rendering

If a certain route needs its own logic, one option is to give it a dedicated renderer.

render('/books/:book', (module, { params }) => {
  return <body>{params.book}</body>
})

Isomorphic rendering

It's important to remember that your renderer will run in both Node and web environments, so you need to be conscious about keeping your code compatible with both.

The one exception to that rule is when a variable is only used for rendering the optional <head> element. Any code used in <head> and not in <body> will be tree-shaked while generating the client renderer.

 

Limitations

To reduce code complexity in the client generator, your render functions have the following limitations.

 

Keep <head> and <body> elements within <html> subtree.

For the <head>-only logic to be tree-shaked, it can't be "lifted" out of the <html> subtree.

// Bad
const Head = () => (
  <head>{...}</head>
)
return (
  <html>
    <Head />
  </html>
)

// Good
return (
  <html>
    <head>{...}</head>
  </html>
)

If you want to reuse <head> children between renderers, you can write a component that returns a JSX fragment containing the scripts, stylesheets, etc. that you wish to share between them.

const SharedHeadTags = () => (
  <>
    <link rel="icon" href="/favicon.ico" type="image/x-icon" />
    <link rel="stylesheet" href="…" />
    <script src="…"></script>
  </>
)

// In your render functions:
return (
  <html>
    <head>
      <SharedHeadTags />
    </head>
  </html>
)

The same limitation applies to the <body> element, but not for tree-shaking reasons.

The <body> element is only required when your render function returns an <html> element. Otherwise, you're free to omit <body> and just return its children. In that case, @saus/react inserts the <body> element in SSR before rendering your JSX into a string, to ensure the HTML is well-formed. If you lift the <body> element into a component, you'll end up with two <body> elements in the HTML string, which is bad.

 

Keep return statements simple.

When returning JSX, prefer if blocks over ternary expressions (eg: a ? <b /> : <c />) or conditional expressions (eg: a && <b />).

// Bad
return condition ? <div /> : <body />

// Good
if (condition) {
  return <div />
}
return <body />

This does not apply to nested elements; just the root element that immediately follows the return keyword. As a rule of thumb, if your element is wrapped in a JSX curly expression (eg: {a && <b />}), any syntax is allowed. Additionally, this rule does not apply to JSX elements in variable declarations (eg: const a = b ? <c /> : <d />).

Wrapping your root element in parentheses is allowed.

return (
  <html>{...}</html>
)
0.4.9

3 years ago

0.4.8

3 years ago

0.3.0

3 years ago

0.2.1

3 years ago

0.2.0

3 years ago

0.1.1

3 years ago

0.4.0

3 years ago

0.3.1

3 years ago

0.2.2

3 years ago

0.1.0

3 years ago