Last active
May 9, 2021 09:44
-
-
Save ianmcnally/291e50b88a861e7da28c8ae3bb538c51 to your computer and use it in GitHub Desktop.
Server rendering React component that fetch data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const React = require('react') | |
const ReactDomServer = require('react-dom/server') | |
const fetch = require('node-fetch') | |
function App(props) { | |
const { repos } = props | |
return React.createElement('p', { | |
children: repos.length ? repos[0].name : 'no name', | |
}) | |
} | |
// the data fetching for the data required in <App> | |
function fetchRepos() { | |
return fetch('https://api.github.com/users/ianmcnally/repos').then( | |
r => r.json(), | |
) | |
} | |
// this could be a default export in App.js, | |
// like you would see, for example, a connected component in a Redux app | |
const WrappedApp = wrapComponentWithPropRendering(App, function() { | |
return fetchRepos().then((repos) => ({ repos })) | |
}, []) | |
// Higher order component (HOC) to set a component up for client and server rendering | |
function wrapComponentWithPropRendering(AnyComponent, dataFetch, initialData) { | |
function WrappedComponent(props) { | |
const [state, setState] = React.useState(initialData) | |
React.useEffect(() => { | |
dataFetch().then(data => { setState(data) }) | |
}, []) | |
return React.createElement(AnyComponent, {...props, ...state}) | |
} | |
// exporting the component will allow the server to render the original component with the props | |
// and would also work in testing to remove data fetching from most tests | |
WrappedComponent.Component = AnyComponent | |
// this is what the server can use to fetch data and render unwrapped component with the correct props, | |
// inspired by Next.js | |
WrappedComponent.getInitialProps = dataFetch | |
return WrappedComponent | |
} | |
// how the server could render this component with data | |
module.exports = async function renderOnServer() { | |
const props = await WrappedApp.getInitialProps() | |
const el = ReactDomServer.renderToString(React.createElement(WrappedApp.Component, props)) | |
console.log('element', el) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: used createElement over JSX so that this didn't need to get compiled when run via node.
To test this, I was launching the node cli then running:
Which I would expect to console log a string version of the element, with the data.