Skip to content

Repository files navigation

πŸ—‚ react-universal-data

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

  • Only 600B minified and gziped
  • Simple hooks API
  • TypeScript
  • Can handle updates
  • Simple cache
  • Suspense on server side via 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

πŸ“¦ Install

$ npm i -S react-universal-data
$ yarn add react-universal-data

πŸ“– Docs

useFetchData

Requests data and preserves the result to the state.

typeuseFetchData<T>=(// async function that can return any type of datafetcher: (key: string,context: {isServer: boolean})=>Promise<T>,// unique key that will be used for storing & hydrating data while SSRkey: string,// use cached value for specified duration of time, by default it will be requested each timettl?: number)=>AsyncState<T>

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

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

exporttypeAsyncState<T>=// 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
importReactfrom'react'import{useFetchData}from'react-universal-data'constfetchPost=(id)=>fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then((response)=>response.json())functionPost({ id }){const{ isReady, isLoading, result, error }=useFetchData(fetchPost,id)if(isLoading){return<p>Loading...</p>}if(error){return<p>Oh no: {error.message}</p>}// You can depend on `isReady` flag to ensure data loaded correctlyif(isReady){return(<article><h2>{result.title}</h2><p>{result.body}</p></article>)}returnnull}

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.

importReact,{useCallback}from'react'import{useFetchData}from'react-universal-data'functionUserPosts({ userId }){constfetchPosts=useCallback(()=>(fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`).then((response)=>response.json())),[userId])// will pereform update if value changedconst{ result =[]}=useFetchData(fetchPosts,'user-posts')return(<ul>{result.map((post)=><likey={post.id}>{post.title}</li>)}</ul>)}
πŸ‘€ Create a custom hook for it
importReact,{useCallback}from'react'import{useFetchData}from'react-universal-data'functionuseFetchUserPosts(userId){returnuseFetchData(useCallback(()=>(fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`).then((response)=>response.json())),[userId]),'user-posts')}functionUserPosts({ userId }){const{ result =[]}=useFetchUserPosts(userId)return(<ul>{result.map((post)=><likey={post.id}>{post.title}</li>)}</ul>)}

getInitialData

Handles useFetchData on server side and gathers results for hydration in the browser.

typegetInitialData=(element: JSX.Element)=>Promise<[string,any][]>
// server.jsimportReactfrom'react'import{renderToString}from'react-dom/server'import{getInitialData}from'react-universal-data'import{App}from'./App'asyncfunctionserver(req,res){constelement=<App/>constdata=awaitgetInitialData(element).catch((error)=>/* handle error */)consthtml=renderToString(<html><body><divid='app'>{element}</div><scriptdangerouslySetInnerHTML={{__html: `window._ssr = ${JSON.stringify(data)};`,}}/><scriptsrc='/client.js'/></body></html>)res.write('<!DOCTYPE html>')res.write(html)res.end()}

hydrateInitialData

Hydrates initial data gathered with getInitialData before rendering the app in the browser.

typehydrateInitialData=(initial: [string,any][])=>void
// client.jsimportReactfrom'react'importReactDOMfrom'react-dom'import{hydrateInitialData}from'react-universal-data'import{App}from'./App'hydrateInitialData(window._ssr||[])ReactDOM.hydrate(<App/>,document.getElementById('app'))

πŸ’» Demo

Edit react-universal-data-ssr

πŸ”— Related

Packages

Real world usages


MIT Β© John Grishin

About

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

Topics

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages