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
- Host: GitHub
- URL: https://github.com/exah/react-universal-data
- Owner: exah
- License: mit
- Created: 2018-06-27T10:08:15.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-05-10T14:31:27.000Z (almost 6 years ago)
- Last Synced: 2025-06-04T04:09:51.317Z (9 months ago)
- Topics: async, hook, isomorphic, prefetch, react, react-dom, server-rendering, small-size, ssr, tiny, universal
- Language: JavaScript
- Homepage: https://bundlephobia.com/result?p=react-universal-data
- Size: 458 KB
- Stars: 13
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# 🗂 react-universal-data
[](https://www.npmjs.com/package/react-universal-data) [](https://bundlephobia.com/result?p=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 (
- {post.title} )}
{result.map((post) =>
)
}
```
👀 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 (
- {post.title} )}
{result.map((post) =>
)
}
```
### `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(
)
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
[](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)