Skip to content

Instantly share code, notes, and snippets.

@armand1m
Created November 15, 2017 22:38
Show Gist options
  • Save armand1m/69e390a681b4a8e0663cdda9df2f6bd4 to your computer and use it in GitHub Desktop.
Save armand1m/69e390a681b4a8e0663cdda9df2f6bd4 to your computer and use it in GitHub Desktop.
Simple HOC for fetching data that is compatible with the SSR technique described by @BenLu here: https://medium.com/@benlu/ssr-with-create-react-app-v2-1-ee83fb767327
import React, { Component } from 'react';
const hasDataForThisKey = (staticContext) =>
(key) => staticContext && Object.keys(staticContext.data).includes(key);
const windowHasDataForThisKey = (window) =>
(key) => Object.keys(window.__DATA__).includes(key);
export default ({
key,
prop,
getData,
}) => (WrappedComponent) => {
class SSRCompatibleComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
async componentWillMount() {
this._handleData();
}
async _handleData() {
const { staticContext } = this.props;
if (hasDataForThisKey(staticContext)(key)) {
const data = staticContext.data[key];
this._setData(data);
} else if (staticContext) {
staticContext.data[key] = this._getData();
} else if (!staticContext && windowHasDataForThisKey(window)(key)) {
const data = window.__DATA__[key];
window.__DATA__[key] = null;
this._setData(data);
} else if (!staticContext) {
const data = await this._getData();
this._setData(data);
}
}
_setData(data) {
this.setState({
...this.state,
[prop]: data,
})
}
async _getData() {
const { props } = this;
const data = await getData({ props });
return data;
}
render() {
return (
<WrappedComponent
{...this.props}
{...this.state}
/>
);
}
}
return SSRCompatibleComponent;
}
@armand1m
Copy link
Author

Using in a component that needs data for server side rendering:

import React from 'react';
import withInitialData from './withInitialData';

const Publication = ({ publication }) => (
  <article>
    <h1>{publication.title}</h1>
    <p>{publication.content}</h1>
  </article>
));

const getInitialData = async ({ props }) => {
  // make async calls here

  return ({
    title: 'test',
    content: 'my content',
  });
};

const EnhancedPublication = withInitialData({
  key: 'PublicationPage',
  prop: 'publication',
  getData: getInitialData,
})(Publication);

export default EnhancedPublication;

@armand1m
Copy link
Author

For details of how to configure your express server to work with this, please see:

https://medium.com/@benlu/ssr-with-create-react-app-v2-1-ee83fb767327

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment