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

https://github.com/exah/react-universal-data

Easy to use React hook for getting data on client and server side with effortless hydration of state
https://github.com/exah/react-universal-data

async hook isomorphic prefetch react react-dom server-rendering small-size ssr tiny universal

Last synced: 8 months ago
JSON representation

Easy to use React hook for getting data on client and server side with effortless hydration of state

Awesome Lists containing this project

README

          

# 🗂 react-universal-data

[![](https://flat.badgen.net/npm/v/react-universal-data?cache=600)](https://www.npmjs.com/package/react-universal-data) [![](https://flat.badgen.net/bundlephobia/minzip/react-universal-data?cache=600)](https://bundlephobia.com/result?p=react-universal-data) ![](https://flat.badgen.net/travis/exah/react-universal-data?cache=600) ![](https://flat.badgen.net/coveralls/c/github/exah/react-universal-data)

#### Easy to use hook for getting data on client and server side with effortless hydration of state

- [x] Only 600B minified and gziped
- [x] Simple hooks API
- [x] TypeScript
- [x] Can handle updates
- [x] Simple cache
- [x] [Suspense](http://reactjs.org/docs/concurrent-mode-suspense.html) on server side via [`react-ssr-prepass`](https://github.com/FormidableLabs/react-ssr-prepass) 💕

> _This is a NO BULLSHIT hook: just PLUG IT in your components, get ALL THE DATA you need (and some more) both CLIENT- and SERVER-side, HYDRATE that ~~bastard~~ app while SSRing like it's NO BIG DEAL, effortlessly PASS IT to the client and render THE SHIT out of it_
>
> [@razdvapoka](https://github.com/razdvapoka)

## 📦 Install

```sh
$ npm i -S react-universal-data
```

```sh
$ yarn add react-universal-data
```

## 📖 Docs

### `useFetchData`

Requests data and preserves the result to the state.

```ts
type useFetchData = (
// async function that can return any type of data
fetcher: (key: string, context: { isServer: boolean }) => Promise,
// unique key that will be used for storing & hydrating data while SSR
key: string,
// use cached value for specified duration of time, by default it will be requested each time
ttl?: number
) => AsyncState
```

> ⚠️ The `key` must be unique for the whole application.

Returned object can be in 4 different forms – depending on the promise's state.

```ts
export type AsyncState =
// initial
| { isReady: false; isLoading: false; error: null; result: undefined }
// fulfilled
| { isReady: true; isLoading: false; error: null; result: T }
// pending
| { isReady: boolean; isLoading: true; error: Error | null; result?: T }
// rejected
| { isReady: false; isLoading: false; error: Error; result?: T }
```

👀 Fetch a sample post via jsonplaceholder.typicode.com API

```js
import React from 'react'
import { useFetchData } from 'react-universal-data'

const fetchPost = (id) =>
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())

function Post({ id }) {
const { isReady, isLoading, result, error } = useFetchData(fetchPost, id)

if (isLoading) {
return

Loading...


}

if (error) {
return

Oh no: {error.message}


}

// You can depend on `isReady` flag to ensure data loaded correctly
if (isReady) {
return (

{result.title}


{result.body}



)
}

return null
}
```

As the hook depends on the `fetcher` function identity to be stable, please, wrap it inside `useCallback` or define it outside of the render function to prevent infinite updates.

```js
import React, { useCallback } from 'react'
import { useFetchData } from 'react-universal-data'

function UserPosts({ userId }) {
const fetchPosts = useCallback(() => (
fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`)
.then((response) => response.json())
), [userId]) // will pereform update if value changed

const { result = [] } = useFetchData(fetchPosts, 'user-posts')

return (


    {result.map((post) =>
  • {post.title}
  • )}

)
}
```

👀 Create a custom hook for it

```js
import React, { useCallback } from 'react'
import { useFetchData } from 'react-universal-data'

function useFetchUserPosts(userId) {
return useFetchData(
useCallback(() => (
fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`)
.then((response) => response.json())
), [userId]),
'user-posts'
)
}

function UserPosts({ userId }) {
const { result = [] } = useFetchUserPosts(userId)

return (


    {result.map((post) =>
  • {post.title}
  • )}

)
}
```

### `getInitialData`

Handles `useFetchData` on server side and gathers results for [hydration](#hydrateInitialData) in the browser.

```ts
type getInitialData = (element: JSX.Element) => Promise<[string, any][]>
```

```js
// server.js
import React from 'react'
import { renderToString } from 'react-dom/server'
import { getInitialData } from 'react-universal-data'
import { App } from './App'

async function server(req, res) {
const element =

const data = await getInitialData(element).catch((error) => /* handle error */)
const html = renderToString(


{element}





)

res.write('')
res.write(html)
res.end()
}
```

### `hydrateInitialData`

Hydrates initial data gathered with [`getInitialData`](#getInitialData) before rendering the app in the browser.

```ts
type hydrateInitialData = (initial: [string, any][]) => void
```

```js
// client.js
import React from 'react'
import ReactDOM from 'react-dom'
import { hydrateInitialData } from 'react-universal-data'
import { App } from './App'

hydrateInitialData(window._ssr || [])
ReactDOM.hydrate(, document.getElementById('app'))
```

## 💻 Demo

[![Edit react-universal-data-ssr](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-universal-data-ssr-jp9el?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.js&theme=dark)

## 🔗 Related

### Packages

- [`react-ssr-prepass`](https://github.com/FormidableLabs/react-ssr-prepass) - server-side dependency
- [`ya-fetch`](https://github.com/exah/ya-fetch) - a lightweight wrapper around `fetch`

### Real world usages

- [kayway.me](https://github.com/exah/kayway)
- [goremykina.com](https://github.com/exah/goremykina)
- [strelkamag.com](https://strelkamag.com)

---

MIT © [John Grishin](http://johngrish.in)