1.0.1 • Published 4 years ago

@brawcode/express-react v1.0.1

Weekly downloads
2
License
MIT
Repository
github
Last release
4 years ago

Express React

A server side React renderer that embeds into your templating language. Inspired by ReactRails/ReactOnRails.

Features

  • Lightweight
  • Full SSR support
  • Typescript

Demos

TODO - Demo for JS version

TODO - Demo for TS version

Installation

Via npm

npm install @brawcode/express-react

Via yarn

yarn add @brawcode/express-react

Setup

Express React has been designed to work as a middleware with ExpressJS. It ensures that the react_render view helper function is exposed to your templating engine. This setup guide assumes you know how to configure webpack and babel.

Add it to your app like so:

import express from "express";
import expressReact from "@brawcode/express-react";

const app = express();
app.use(expressReact());

We now need to do 3 things.

  • Create and register a React component
  • Render that component in a view on the server
  • Sync client and server DOM (hydrate)

We will keep it simple and create a HelloReact component.

import React from "react";

export const HelloReact = () => {
  return <h1>Hello!</h1>;
};

Create a file called register.js somewhere in your project. (I create mine under assets/javascripts). In here we are going to import our component and register it. The name is what you will use to reference it when you render it in your views, so make it something meaningful.

import { registerComponent } from "@brawcode/express-react";
import { HelloReact } from "./components/HelloReact";

registerComponent({
  Component: HelloReact,
  name: "hello-react",
});

I am a big fan of the Pug templating language but you can use whatever template language you like. Here is my simple Pug template.

html
  head
    title Hello Express!
  body
    =! react_render("hello-react")

In here we call react_render and pass it the name of the component we want to render. Simple! By default this will render your component on the server before sending the markup to the front end. However, we are missing once thing. We want to make the component reactive right?

Add a new js file called application.js and include it in your template via a script tag. In pug this would look like this:

script(src="/dist/javascripts/application.bundle.js")

This assumes that your webpack is configured to output a file called application.bundle.js into the dist folder whenever you compile.

In application.js all we have to do is tell ExpressReact that this code is client side, and it should hydrate the DOM. It looks a like this:

import { client } from "@brawcode/express-react";

client();

That's it. ExpressReact will hydrate the dom and attach event listeners as required and now your component will be reactive! You can test this by adding some state, and a button to do some stuff:

export const HelloReact = () => {
  const [counter, setCounter] = useState(0);
  return (
    <div>
      <h1>Hello!</h1>
      <p> Counter: {counter}</p>
      <button onClick={() => setCounter(counter + 1)}>Increase</button>
    </div>
  );
};

Passing props

It would be a bit pointless if you couldn't pass props to your component serverside! All we have to do is change our react_render call to take some props.

=! react_render("hello-react", { name: "Bobby" })

Or you could use a variable from express.

router.get("/", (req, res) => {
  render("path/to/your/view/template", { name: "Bobby" });
});
=! react_render("hello-react", { name })

In our component, we just treat it as normal props:

export const HelloReact = ({ name }) => {
  return <h1>Hello {name}!</h1>;
};

Static props

There is some but limited support for static props. These are props that are passed into your component without you having to do to it every time. You can do this by changing how you add the middleware:

app.use(
  expressReact({
    name: "Bobby",
  })
);

Now the name prop will be available in all registered components even if you don't pass them during render.

Render options

You can pass a per render options object when you call react_render to customize how that render will behave.

=! react_render("hello-react", { name }, { /** options here */})

Options

// Available options and their defaults
{
  /**
   * Enables or disables server side rendering for the given component.
   * This may improve performance on the server, large components that don't need to
   * be rendered serverside can be client only
   */
  ssr: true;
}

Typescript

Typescript support is included and the types are documented.


Contributing

You are free to contribute to this project in anyway you see fit. A few good places to start is better static prop support and more test coverage.

License

MIT