Skip to content

hapi route to delegate routing for html content to react-router

License

Notifications You must be signed in to change notification settings

travi/hapi-react-router

Repository files navigation

hapi-react-router

hapi route to delegate routing for html content to react-router v3

Build Status Codecov Node CI Workflow Status

Table of Contents

Usage

npm node license Try @travi/hapi-react-router on RunKit

Installation

$ npm install @travi/hapi-react-router -S

⚠️ this plugin expects external babel-helpers to be provided by the consumer

Register with your Hapi v18+ server

Include this plugin in the manifest of your hapi application to direct all requests to /html to a server-side renderer for your react-router routes. It is assumed that something (not included) is in place to direct all text/html requests to this /html route.

In addition, redial fetch hooks will be triggered and rendering will wait for all related requests to complete. This enables populating the data store based on the components that are mounted for the current route. See redial arguments for the list of arguments supplied to triggered fetches.

Example

Dependencies:

import React from 'react';
import {IndexRoute, Route} from 'react-router';
import {createStore} from 'redux';
import {Provider} from 'react-redux';

Register with the Hapi server

export default {
  server: {port: process.env.PORT},
  register: {
    plugins: [
      {plugin: '@travi/hapi-html-request-router'},
      {
        plugin: '@travi/hapi-react-router',
        options: {
          respond: (reply, {renderedContent}) => {
            reply.view('layout', {renderedContent});
          },
          routes: (
            <Route path="/" component={Wrap}>
              <IndexRoute component={Index} />
              <Route path="/foo" component={Foo} />
              <Route path="/bar" component={Bar} />
              <Route path="*" component={NotFound} />
            </Route>
          ),
          Root: ({store, children}) => (
            <Provider store={store}>
              {children}
            </Provider>
          ),
          configureStore: ({session}) => createStore(reducer, composeMiddlewares(session)),
Optional custom renderer that passes blankie (optional to provide yourself) nonces as a prop
          render: (defaultRender, request) => ({html: defaultRender({nonces: request.plugins.blankie.nonces})})
        }
      }
    ]
  }
};

Dependencies for you to provide

This plugin provides you the ability to customize a few steps of the process. Default implementations are currently not provided, so these dependencies are required.

  • respond: a function that will that allows you to call reply on your own, allowing you to perform additional steps before the response
  • routes: the definition of your react-router routes that this plugin should match the request url against
    • If you use a catch-all route to display an appropriate message when the route does not match, it should have a displayName of NotFound. This will enable the status code to be passed to respond as 404. Please note that the automatic mapping of the name property should not be relied on because it can be mangled during minification and, therefore, not match in production.
  • Root: a react component that will wrap the mounted components that result from the matched route
  • store: a data store that will be passed as a prop to the <Root /> component so that your component can inject it into the context through a provider component.
  • render: optional custom renderer to replace the default renderer. Passed defaultRenderer and request as arguments so additional props can be passed to the defaultRenderer, potentially from the request.

Redial fetch trigger arguments

  • params: pass-through of react-router params taken from the path
  • dispatch: redux store dispatch method
  • state: current state of the redux store
  • getState: method to get the latest state of the redux store
  • store: the raw redux store. ⚠️ WARNING: this should only be used for unique circumstances (e.g., creating a custom subscription to the store)

Contribution

Commitizen friendly semantic-release Renovate

Install dependencies

$ nvm install
$ npm install

Verification

$ npm test

Run the example app

$ npm start