Skip to content

Instantly share code, notes, and snippets.

@jaredpalmer
Last active August 1, 2019 00:40
Show Gist options
  • Save jaredpalmer/d0b91593f6baaa2f2867d133a26f4176 to your computer and use it in GitHub Desktop.
Save jaredpalmer/d0b91593f6baaa2f2867d133a26f4176 to your computer and use it in GitHub Desktop.
SSR HOC
import React from 'react';
import axios from 'axios';
// This is a Higher Order Component that abstracts duplicated data fetching
// on the server and client.
export default function SSR(Page) {
class SSR extends React.Component {
static getInitialData(ctx) {
// Need to call the wrapped components getInitialData if it exists
return Page.getInitialData
? Page.getInitialData(ctx)
: Promise.resolve(null);
}
state = {
data: this.props.initialData,
isLoading: !!this.props.initialData,
};
componentDidMount() {
if (!this.state.data) {
this.fetchData();
}
}
fetchData = () => {
// if this.state.data is null, that means that the we are on the client.
// To get the data we need, we just call getInitialData again on mount.
console.log('refetching');
this.setState({ isLoading: true });
this.constructor.getInitialData({ match: this.props.match, axios }).then(
data => {
this.setState({ data, isLoading: false });
},
error => {
this.setState(state => ({
data: { error },
isLoading: false,
}));
}
);
};
render() {
// Flatten out all the props.
const { initialData, ...rest } = this.props;
return (
<Page
{...rest}
refetch={this.fetchData}
isLoading={this.state.isLoading}
{...this.state.data}
/>
);
}
}
SSR.displayName = `SSR(${getDisplayName(Page)})`;
return SSR;
}
// This make debugging easier. Components will show as SSR(MyComponent) in
// react-dev-tools.
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment