Skip to content

Commit

Permalink
Merge pull request #2 from POORYAJ/pr/remove-withssrdata
Browse files Browse the repository at this point in the history
Remove the need to wrap views in 'withSSRData'
  • Loading branch information
iMohammadReza authored Jun 6, 2021
2 parents 908557f + 9383daa commit 2723316
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 10 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Runs linter.
Only views can be SSR. Views are components that directly connected to a URL. To do SSR you need just 2 simple steps:


* Add `serverSideInitial` static method to your view to do side-effects, dispatch actions to store or return values and promises.
* Just add `serverSideInitial` static method to your view to do side-effects, dispatch actions to store or return values and promises.

```
static serverSideInitial({ dispatch, req }) {
Expand All @@ -85,15 +85,15 @@ Only views can be SSR. Views are components that directly connected to a URL. To
```

* Wrap the view with `withSSRData` HOC to get value returned by `serverSideInitial` as `props.initialSSRData`.
* Now get value returned by `serverSideInitial` as `props.initialSSRData`.

```
Component.propTypes = {
initialSSRData: PropTypes.shape({
posts: PropTypes.array(),
};
export default withSSRData(Component);
export default Component;
```

## Directory Layout
Expand Down
4 changes: 2 additions & 2 deletions src/AppRouter.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { renderRoutes } from 'react-router-config';

import routes from 'src/configs/routes';

import { renderRoutes } from './server/utils';

function AppRouter() {
return renderRoutes(routes);
}
Expand Down
1 change: 1 addition & 0 deletions src/configs/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Home from 'src/views/Home';

const routes = [
{
path: '/',
component: Home,
},
];
Expand Down
23 changes: 19 additions & 4 deletions src/server/handlers/ssr-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { initSSRContextValue } from 'src/services/initial-ssr-data/utils';
import { getEnv, isProd } from 'src/utils/env';
import AppRouter from 'src/AppRouter';

import { findFinalComponent } from '../utils';
import { findFinalComponent, getComponent } from '../utils';
import pageTemplate from '../templates/page-template.hbs';

// eslint-disable-next-line import/no-dynamic-require
Expand Down Expand Up @@ -45,22 +45,37 @@ function renderPage({ appHtml, preloadedData, preloadedState }) {

function getInitialPropsList({ renderBranch, store: { getState, dispatch }, req }) {
return renderBranch.reduce(
(initialPropsList, { route: { component, path } }) => {
(
initialPropsList,
{
route:
{
component: routeComponent,
render: routeRenderer, path,
},
},
) => {
const component = getComponent(routeComponent, routeRenderer);

// Due to usage of HOCs, we have to traverse the component tree
// to find the final wrapped component which contains the static server-side methods
const {
component: { serverSideInitial },
hasSSRData: hasPreloadedData,
hasSSRData: wrappedInWithSSRData,
} = findFinalComponent(component);

if (!serverSideInitial) {
return initialPropsList;
}

const dataPromise = serverSideInitial({ getState, dispatch, req });
const serverSideInitialReturns = dataPromise !== undefined;
const hasPreloadedData = serverSideInitialReturns || wrappedInWithSSRData;

return initialPropsList.concat({
path,
hasPreloadedData,
dataPromise: serverSideInitial({ getState, dispatch, req }),
dataPromise,
});
},
[],
Expand Down
45 changes: 45 additions & 0 deletions src/server/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import React from 'react';
import { Switch, Route } from 'react-router-dom';

import { getEnv } from 'src/utils/env';
import withSSRData from 'src/services/initial-ssr-data/withSSRData';

// Due to usage of HOCs, we have to traverse the component tree to find the
// final wrapped component which contains the static server-side methods
Expand All @@ -20,3 +24,44 @@ export function findFinalComponent(component) {
hasSSRData: isWrappedInWithSSRDataHOC,
};
}

export function getComponent(component, routeRenderer) {
// because route renderers are a wrapper around the actual component,
// they return the element created by react and not the actual component so we
// need to point to the actual component which is stored in the 'type' property
// in the returned react element
const reactElement = routeRenderer ? routeRenderer() : null;

return reactElement ? reactElement.type : component;
}

export function renderRoutes(routes, extraProps = {}, switchProps = {}) {
if (!routes) return null;

return (
<Switch {...switchProps}>
{routes.map((route, index) => {
const { component: routeComponent, render: routeRenderer, ...rest } = route;
const component = getComponent(routeComponent, routeRenderer);
const { hasSSRData: wrappedInWithSSRData } = findFinalComponent(component);
const hasServerSideInitial = component.serverSideInitial;
const needsWithSSRData = hasServerSideInitial && !wrappedInWithSSRData;

/* eslint react/no-array-index-key: 0 */
return (
<Route
key={`route--${index}`}
{...rest}
render={(props) => {
const componentProps = { ...props, ...extraProps, route };

return (needsWithSSRData)
? React.createElement(withSSRData(component), componentProps)
: React.createElement(component, componentProps);
}}
/>
);
})}
</Switch>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React, { Component } from 'react';
import { withRouter } from 'react-router';
import PropTypes from 'prop-types';

import { getContext } from 'src/services/initial-ssr-data';
import { getDisplayName } from 'src/utils/hoc';
import { getEnv } from 'src/utils/env';

import { getContext } from './index';

function withSSRData(WrappedComponent) {
class WithSSRDataComponent extends Component {
componentWillUnmount() {
Expand Down

0 comments on commit 2723316

Please sign in to comment.