
- ReactJS - Home
- ReactJS - Introduction
- ReactJS - Roadmap
- ReactJS - Installation
- ReactJS - Features
- ReactJS - Advantages & Disadvantages
- ReactJS - Architecture
- ReactJS - Creating a React Application
- ReactJS - JSX
- ReactJS - Components
- ReactJS - Nested Components
- ReactJS - Using Newly Created Components
- ReactJS - Component Collection
- ReactJS - Styling
- ReactJS - Properties (props)
- ReactJS - Creating Components using Properties
- ReactJS - props Validation
- ReactJS - Constructor
- ReactJS - Component Life Cycle
- ReactJS - Event management
- ReactJS - Creating an Event−Aware Component
- ReactJS - Introduce Events in Expense Manager APP
- ReactJS - State Management
- ReactJS - State Management API
- ReactJS - Stateless Component
- ReactJS - State Management Using React Hooks
- ReactJS - Component Life Cycle Using React Hooks
- ReactJS - Layout Component
- ReactJS - Pagination
- ReactJS - Material UI
- ReactJS - Http client programming
- ReactJS - Form Programming
- ReactJS - Controlled Component
- ReactJS - Uncontrolled Component
- ReactJS - Formik
- ReactJS - Conditional Rendering
- ReactJS - Lists
- ReactJS - Keys
- ReactJS - Routing
- ReactJS - Redux
- ReactJS - Animation
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - Table
- ReactJS - Managing State Using Flux
- ReactJS - Testing
- ReactJS - CLI Commands
- ReactJS - Building and Deployment
- ReactJS - Example
- Hooks
- ReactJS - Introduction to Hooks
- ReactJS - Using useState
- ReactJS - Using useEffect
- ReactJS - Using useContext
- ReactJS - Using useRef
- ReactJS - Using useReducer
- ReactJS - Using useCallback
- ReactJS - Using useMemo
- ReactJS - Custom Hooks
- ReactJS Advanced
- ReactJS - Accessibility
- ReactJS - Code Splitting
- ReactJS - Context
- ReactJS - Error Boundaries
- ReactJS - Forwarding Refs
- ReactJS - Fragments
- ReactJS - Higher Order Components
- ReactJS - Integrating With Other Libraries
- ReactJS - Optimizing Performance
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - React Without ES6 ECMAScript
- ReactJS - React Without JSX
- ReactJS - Reconciliation
- ReactJS - Refs and the DOM
- ReactJS - Render Props
- ReactJS - Static Type Checking
- ReactJS - Strict Mode
- ReactJS - Web Components
- Additional Concepts
- ReactJS - Date Picker
- ReactJS - Helmet
- ReactJS - Inline Style
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - Carousel
- ReactJS - Icons
- ReactJS - Form Components
- ReactJS - Reference API
- ReactJS Useful Resources
- ReactJS - Quick Guide
- ReactJS Cheatsheet
- Axios CheatSheet
- ReactJS - Useful Resources
- ReactJS - Discussion
ReactJS - use Hook
As we know in React a "hook" is a special function that lets us add state and other React features to our functional components. So 'use' is a React Hook that reads the value of a resource, such as a Promise or context. Unlike all other React Hooks, use can be invoked within loops and conditional expressions like if. The function that calls use, like all other React Hooks, must be a Component or Hook.
Basic syntax for use hook
const data = use(asset);
Parameters
asset − It is the source of the data we want to read a value from. So this can be a Promise or a context.
Return Value
This Hook will return the value read from the asset, similar to how a Promise or context's resolved value is returned.
Usage of use Hook
import { use } from 'react'; function TheComponent ({ thePromise }) { const msg = use(thePromise); const data = use(DataContext); // ...
The use hook with Promise
So by using a promise with the use hook we can stream data from server to the client. By providing a Promise as a prop from a Server Component to a Client Component, data can be sent from the server to the client.
import { Data } from './data.js'; export default function App() { const dataPromise = fetchData(); return ( <Suspense fallback={<p>waiting for the data...</p>}> <Message dataPromise={dataPromise} /> </Suspense> ); }
The Client Component then passes the Promise it was given as a prop to the use Hook. This enables the Client Component to read the value from the Promise that the Server Component first produced.
data.js
'use client'; import { use } from 'react'; export function Data({ dataPromise }) { const dataContent = use(dataPromise); return <h4>Here is the data: {dataContent}</h4>; }
Due to the fact that Data is wrapped in Suspense, the fallback will be shown until the Promise is resolved. When the Promise is resolved, the value is read by the Hook, and the Data component takes the place of the Suspense fallback.
Complete code
Data.js
"use client"; import { use, Suspense } from "react"; function Data({ dataPromise }) { const dataContent = use(dataPromise); return <h4>Yup!!! Here is the Data: {dataContent}</h4>; } export function DataContainer({ dataPromise }) { return ( <Suspense fallback={<p>⌛ Downloading Data...</p>}> <Data dataPromise={dataPromise} /> </Suspense> ); }
App.js
import { useState } from "react"; import { DataContainer } from "./data.js"; function fetchData() { return new Promise((resolve) => setTimeout(resolve, 2000, "😃")); } export default function App() { const [dataPromise, setDataPromise] = useState(null); const [show, setShow] = useState(false); function download() { setDataPromise(fetchData()); setShow(true); } if (show) { return <DataContainer dataPromise={dataPromise} />; } else { return <button onClick={download}>Download Your Data</button>; } }
Output

How to deal with rejected Promise
Sometimes a Promise passed to use hook can be rejected. So we can handle these rejected Promises displaying an error to users with error boundary or by providing a different value with Promise.catch.
Using an error boundary to display an error to users
Assume we want to show our users an error when the Promise is refused, therefore we can use an error boundary. To do this, we can place an error boundary around the component where we are calling the use Hook. If the Promise given to use is refused, the error boundary's fallback will be shown.
Example
ItemListContainer.js
import { use, Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; export function ItemListContainer({ itemListPromise }) { return ( <ErrorBoundary fallback={<p>⚠ Something went wrong</p>}> <Suspense fallback={<p>⌛ Loading items...</p>}> <ItemList itemListPromise={itemListPromise} /> </Suspense> </ErrorBoundary> ); } function ItemList({ itemListPromise }) { const items = use(itemListPromise); return ( <div> <h2>Item List:</h2> <ul> {items.map((item, index) => ( <li key={index}>{item}</li> ))} </ul> </div> ); }
App.js
import { useState } from "react"; import { ItemListContainer } from "./ItemListContainer"; function fetchItems() { return new Promise((resolve) => setTimeout(() => resolve(["Item 1", "Item 2", "Item 3"]), 1000) ); } function App() { const [itemListPromise, setItemListPromise] = useState(null); const [show, setShow] = useState(false); function loadItems() { setItemListPromise(fetchItems()); setShow(true); } if (show) { return <ItemListContainer itemListPromise={itemListPromise} />; } else { return <button onClick={loadItems}>Load Items</button>; } } export default App;
Output

Using Promise.catch to provide an alternate value
If the Promise supplied is rejected, we can use the catch method to supply an alternate value.
import { Data } from './data.js'; export default function App() { const dataPromise = new Promise((resolve, reject) => { reject(); }).catch(() => { return "No data found."; }); return ( <Suspense fallback={<p>waiting for the data...</p>}> <Data dataPromise={dataPromise} /> </Suspense> ); }
The use hook with Context
Let us see another example of the use hook. So we will be using the use function with a context in React −
In this example we will have a context for managing the theme; it can be light or dark. Then we will have a main app component called MyUseHookApp. It is the top-level component that provides the 'light' theme and will render a form component. Then we will create a form component called MyForm, which is a component that will render a panel and three buttons. After that the panel component is named MyPanel. It will display content with a theme based on the context. And the MyButton component shows a button with a theme as per the context.
Here all the components use the 'use' hook to access the theme from the context and allow them to style elements according to the selected theme.
Example
import { use, createContext } from 'react'; // Create a context for theme const ThemeContext = createContext(null); // Main App component. export default function MyUseHookApp() { return ( // light theme to all components <ThemeContext.Provider value="light"> <MyForm /> </ThemeContext.Provider> ) } // Form component function MyForm() { return ( <MyPanel title="Welcome To My App"> <MyButton show={true}>Join Here</MyButton> <MyButton show={true}>Begin</MyButton> <MyButton show={false}>Settings</MyButton> </MyPanel> ); } // Panel component to display content with a theme function MyPanel({ title, children }) { const theme = use(ThemeContext); // Apply the theme const className = 'panel-' + theme; return ( <section className={className}> <h1>{title}</h1> {children} </section> ) } // Button component function MyButton({ show, children }) { if (show) { const theme = use(ThemeContext); // Apply the theme to the component. const className = 'button-' + theme; return ( <button className={className}> {children} </button> ); } // If 'show' is false, return nothing. return false; }
Output

Drawback
Just like useContext, use(context) regularly looks for the nearest context provider above the calling component. It looks up and ignores context providers in the component from which it's calling use(context).
Limitations
We should use the 'use' Hooks inside our components or hook.
When we are on the server we should always use "async" and "await" to fetch data nicely.
If we need promises, make them on the server because they stay steady, but on the client side, they can change a lot.
It is all about making our web pages work better and more efficiently.