Skip to content

revelrylabs/elixir_react_render

Repository files navigation

ReactRender

Build Status Hex.pm License: MIT Coverage Status

Renders React as HTML

Documentation

The docs can be found at https://hexdocs.pm/react_render.

Installation

def deps do
  [
    {:react_render, "~> 3.0.0"}
  ]
end

Getting Started with Phoenix

  • Add react_render to your dependencies in package.json

    "react_render": "file:../deps/react_render"
  • Run npm install

    npm install
  • Create a file named render_server.js in your assets folder and add the following

    require('@babel/polyfill')
    require('@babel/register')({cwd: __dirname})
    
    module.exports = require('react_render/priv/server')

    Note: You must move any @babel used for server-side rendering from devDependencies to dependencies in your package.json file. This is required when installing dependencies required for production as these packages.

  • Add ReactRender to your Supervisor as a child. We're using the absolute path to ensure we are specifying the correct working directory that contains the render_server.js file we created earlier.

      render_service_path = "#{File.cwd!}/assets"
      pool_size = 4
    
      supervisor(ReactRender, [[render_service_path: render_service_path, pool_size: 4]])
  • Create a react component like:

    import React, {Component, createElement} from 'react'
    
    class HelloWorld extends Component {
      render() {
        const {name} = this.props
    
        return <div>Hello {name}</div>
      }
    }
    
    export default HelloWorld
  • Call ReactRender.render/2 inside the action of your controller

    def index(conn, _params) do
      component_path = "#{File.cwd!}/assets/js/HelloWorld.js"
      props = %{name: "Revelry"}
    
      { :safe, helloWorld } = ReactRender.render(component_path, props)
    
      render(conn, "index.html", helloWorldComponent: helloWorld)
    end

    component_path can either be an absolute path or one relative to the render service. The stipulation is that components must be in the same path or a sub directory of the render service. This is so that the babel compiler will be able to compile it. The service will make sure that any changes you make are picked up. It does this by removing the component_path from node's require cache. If do not want this to happen, make sure to add NODE_ENV to your environment variables with the value production.

  • Render the component in the template

    <%= raw @helloWorldComponent %>
  • To hydrate server-created components in the client, add the following to your app.js

    import {hydrateClient} from 'react_render/priv/client'
    import HelloWorld from './HelloWorld.js'
    
    function getComponentFromStringName(stringName) {
      // Map string component names to your react components here
      if (stringName === 'HelloWorld') {
        return HelloWorld
      }
    
      return null
    }
    
    hydrateClient(getComponentFromStringName)
  • Update assets/webpack.config to include under the resolve section so that module resolution is handled properly:

    resolve: {
      symlinks: false
    }