An open API service indexing awesome lists of open source software.

https://github.com/estrattonbailey/react-hydrate

Generic data fetching, caching, and SSR hydration pattern for React
https://github.com/estrattonbailey/react-hydrate

async react react-ssr

Last synced: over 1 year ago
JSON representation

Generic data fetching, caching, and SSR hydration pattern for React

Awesome Lists containing this project

README

          

# react-hydrate
Generic data fetching and SSR hydration pattern for React.

[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](http://standardjs.com)

## Features & Goals
1. Co-locate data dependencies with your components
2. Supports infinitely nested loaders
3. Fetches requested data on the server and hydrates on the client for a fast startup
4. Wraps components so users can easily define loading states for components
5. Routing agnostic. **Works with `react-router` v4.**
6. Lightweight **~1.9kb**

Related: [react-hydrate-link](https://github.com/estrattonbailey/react-hydrate-link) - prefetch data for your next route using react-router v4.

## Usage
### Defining components
```javascript
/**
* Projects.js
*/
import api from 'my-api'
import { hydrate } from 'react-hydrate'
import Project from './Project.js'

export default hydrate(
/**
* dataLoader receives component props
* and any state already in the store
*/
(props, state) => {
return api.fetchProjects().then(projects => {
return {
projects: projects
}
})
},
/**
* mapStateToProps receives the
* loaded data via `state` and any
* component props.
*
* You should return `false` here if
* the data needed is not yet availabe.
* If a falsy value is returned, it
* tells the library that the loader
* hasn't been run yet or hasn't
* yet resolved.
*/
(state, props) => {
return state.projects ? {
projects: state.projects
} : false
}
)(({ loading, data, ...inheritedProps }) => {
/**
* Component is always passed a loading
* prop that represents the status of their
* dataLoader function
*/
return loading ? (

Loading data...

) : (
data.projects.map(project => )
)
})
```

```javascript
/**
* App.js
*/
import React from 'react'
import Projects from './Projects.js'

export default props => (




)
```

### Creating root app
```javascript
import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter as Router } from 'react-router-dom'
import { Tap } from 'react-hydrate'
import App from './App'

render((





), document.getElementById('root'))
```

### Server
```javascript
import React from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter: Router } from 'react-router'
import { Tap, createStore } from 'react-hydrate'
import { asyncRender } from 'react-hydrate/dist/server'
import App from './App.js'

app.use((req, res) => {
const ctx = {}
const store = createStore({})

const Root = (





)

asyncRender(Root).then(() => {
const state = store.getState()
const content = renderToString(Root)

if (ctx.url) {
res.writeHead(302, {
Location: ctx.url
})
res.end()
} else {
res.send(`




${content}

window.__hydrate = ${JSON.stringify(state)}




`)
res.end()
store.clearState()
}
})
})
```

## Dependencies
- [react-tree-walker:](https://github.com/ctrlplusb/react-tree-walker) Walk a React element tree. by [@ctrlplusb](https://github.com/ctrlplusb)

MIT License