UNPKG

@before.js/client

Version:

Enables data fetching with any React SSR app that uses React Router 5

60 lines (54 loc) 1.69 kB
// @flow strict import type { Route } from 'ensureReady'; import { matchPath } from 'react-router-dom'; import { path } from 'ramda'; import { findRouteByPathname, isClientSide } from './utils'; import { loadableReady } from '@loadable/component'; /** * Verify if given route has a component with an static load method. * @func * @param {object} asyncRoute route to check * @returns {boolean} */ const routeHasComponentLoad = path(['component', 'load']); /** * This helps us to make sure all the async code is loaded before rendering. * @func * @param {array} routes an array of async routes * @param {string} pathname defaults to window.location.pathname */ export async function loadCurrentRoute( routes: Array<Route>, pathname: string = window.location.pathname ) { let data; const route = findRouteByPathname(pathname, routes); if (route) { const match = matchPath(pathname, route); if (match && routeHasComponentLoad(route)) { await route.component.load(); } } if (isClientSide()) { const state = document.getElementById('server-app-state'); const textContent = path(['textContent'], state); try { data = textContent && JSON.parse(textContent); } catch (error) { console.error('There was an error parsing the server-app state', error, textContent); } } return Promise.resolve(data); } /** * Wraps react root mount with @loadable. * @func * @param {function} rootFn a react mount root function * @returns {Promise} */ export function ensureReady( routes: Array<Route>, rootFn: (data: ?{ [key: string]: string }) => void ) { return loadableReady(() => loadCurrentRoute(routes).then(rootFn)); }