hapi route to delegate routing for html content to react-router v3
$ npm install @travi/hapi-react-router -S
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.
import React from 'react';
import {IndexRoute, Route} from 'react-router';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
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)),
render: (defaultRender, request) => ({html: defaultRender({nonces: request.plugins.blankie.nonces})})
}
}
]
}
};
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 callreply
on your own, allowing you to perform additional steps before the responseroutes
: 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
ofNotFound
. This will enable the status code to be passed torespond
as404
. Please note that the automatic mapping of thename
property should not be relied on because it can be mangled during minification and, therefore, not match in production.
- If you use a catch-all route
to display an appropriate message when the route does not match, it should
have a
Root
: a react component that will wrap the mounted components that result from the matched routestore
: 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. PasseddefaultRenderer
andrequest
as arguments so additional props can be passed to the defaultRenderer, potentially from the request.
params
: pass-through of react-router params taken from the pathdispatch
: redux store dispatch methodstate
: current state of the redux storegetState
: method to get the latest state of the redux storestore
: the raw redux store.⚠️ WARNING: this should only be used for unique circumstances (e.g., creating a custom subscription to the store)
$ nvm install
$ npm install
$ npm test
$ npm start