Simple HOC and utils for getting initial and subsequent async data inside React components
- Promise based
- Request data inside HOC or React Component
getData
static prop - Simple server-side rendering & client state restoration
- Can handle updates
$ yarn add react-universal-data
Inside withData
HOC
import 'isomorphic-fetch'
import React from 'react'
import ReactDOM from 'react-dom'
import { withData } from 'react-universal-data'
const Page = ({ user = {} }) => <div>Hello {user.name}!</div>
const PageWithData = withData(() =>
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(res => res.json())
.then(user => ({ user }))
)(Page)
ReactDOM.render(<PageWithData />, document.getElementById('root'))
Or with static getData
prop inside React Component
import 'isomorphic-fetch'
import React from 'react'
import ReactDOM from 'react-dom'
import { withData } from 'react-universal-data'
class Page extends React.Component {
static defaultProps = {
user: {}
}
static async getData() {
const user = await fetch(
'https://jsonplaceholder.typicode.com/users/1'
).then(res => res.json())
return {
user
}
}
render() {
const { user } = this.props
return <div>Hello {user.name}!</div>
}
}
const PageWithData = withData()(Page)
ReactDOM.render(<PageWithData />, document.getElementById('root'))
With two-step rendering on server
// server.js
import React from 'react'
import { renderToString } from 'react-dom/server'
import { getInitialData } from 'react-universal-data'
import { html } from 'common-tags'
import App from './app'
export default () => (req, res) => {
const appElement = (<App />)
getInitialData(appElement)
.then((initialData) => {
res.send(html`
<!DOCTYPE html>
<html>
<body>
<div id="app">${renderToString(appElement)}</div>
<script>
(function () {
window._ssr = ${JSON.stringify({ initialData })};
})();
</script>
<script src="/client.js"></script>
</body>
</html>
`)
})
.catch((error) => {
console.error(error)
res.status(500)
res.send(`Error: ${error.message}`)
})
}
Hydrate App
and initialData
in client
// client.js
import React from 'react'
import ReactDOM from 'react-dom'
import { hydrateData } from 'react-universal-data'
import App from './app'
// Get server state
const { initialData } = (window._ssr || {})
// Restore app state
hydrateData(initialData)
// Render app
ReactDOM.hydrate((
<App />
), document.getElementById('app'))
- react-tree-walker - inside
getInitialData
- webpack-hot-server-middleware - server-side entry for webpack
- goremykina.com - usage example
MIT © John Grishin