Skip to content

Instantly share code, notes, and snippets.

@ianmcnally
Last active May 9, 2021 09:44
Show Gist options
  • Save ianmcnally/291e50b88a861e7da28c8ae3bb538c51 to your computer and use it in GitHub Desktop.
Save ianmcnally/291e50b88a861e7da28c8ae3bb538c51 to your computer and use it in GitHub Desktop.
Server rendering React component that fetch data
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)
}
@ianmcnally
Copy link
Author

Worked on making it more fleshed out here: https://github.com/ianmcnally/node-server-render-react

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