New Hooks in React 18
Last Updated :
09 Jan, 2024
React’s state, representing dynamic component data, is integral for effective component management. Initially confined to class components and managed using this.setState
, the introduction of React Hooks in version 16.8 extended state usage to functional components. Hooks, functions enabling state and lifecycle management in functional components, provide a more versatile approach to React development.
There are several built-in hooks in React, today we are going to see new React hooks that are introduced in React 18.
useId:
useId hook is one of the simplest hooks in react js and it is used to generate unique id’s for related elements on both client-side and server-side. The useOpaqueIdentifierhook was used before useId but it did contain some bugs and had its limitations with react 18 update react introduced useId with bug fixes.
Importing useId hook:
import { useId } from "react"
Syntax:
const id = useId()
useId does not take any parameters.
Example: below is the practical example of useId hook
Javascript
import Component from "./Component" ;
function App() {
return (
<div className= "App" >
<Component />
<p>
This is Paragraph
</p>
<Component />
</div>
);
}
export default App;
|
Javascript
import React, { useId } from 'react'
function Component() {
const id = useId()
return (
<div>
<label htmlFor={id}>Field 1:</label>
<input
type= "text"
id={id}
/>
</div>
)
}
export default Component
|
Output:
Output
useDeferredValue:
- In React 18, addressing sluggish rendering is a key goal, and
useDeferredValue
and useTransition
hooks are introduced for this purpose.
- When rendering a component multiple times for a large number of inputs, React’s efficiency can be compromised, leading to delays and slower render times.
useDeferredValue
is a React Hook that postpones updating a portion of the UI. It introduces a delay in updating the hook value, enhancing user experience by preventing immediate rendering and allowing a smoother display of characters as the user types.
Importing:
import { useDeferredValue } from 'react'
Syntax:
const deferredValue = useDeferredValue(value);
Example: below is the practical example of useDeferredValue hook
Javascript
import React, { useState } from 'react' ;
import DisplayInput from './DisplayInput' ;
function App() {
const [userInput, setUserInput] = useState( '' );
const handleInputChange = (e) => {
setUserInput(e.target.value);
};
return (
<div>
<label htmlFor= "userInput" >
Enter Text:
</label>
<input
type= "text"
id= "userInput"
value={userInput}
onChange={handleInputChange} />
<DisplayInput input={userInput} />
</div>
);
}
export default App;
|
Javascript
import React,
{ useDeferredValue } from 'react' ;
function DisplayInput({ input }) {
const deferredValue =
useDeferredValue(input);
const renderInputs = () => {
const inputs = [];
for (let i = 0; i < 20000; i++) {
inputs.push(
<div key={i}>
{deferredValue}
</div>
);
}
return inputs;
};
return (
<div>
<h2>
Displaying
{deferredValue}
</h2>
{renderInputs()}
</div>
);
}
export default DisplayInput;
|
Output: There is no delay in updation of input in input box.
Output
useTransition:
useTransition
addresses performance concerns in React applications by enhancing UI responsiveness, ensuring a smoother user experience even during background processing.
- In scenarios like a search component with dynamic filtering, where multiple states are updated simultaneously (e.g., search input and filtered results), React’s default high-priority updates can lead to potential slowdowns.
- The issue arises when managing numerous user inputs, causing delays in updating states and impacting user interaction.
useTransition
resolves this by allowing low-priority state updates through the startTransition function, preventing UI blocking and optimizing overall performance.
Import:
import { useTransition } from 'react'
Syntax:
const [isPending, startTransition] = useTransition()
Example: below is the practical example of useTransition hook
Javascript
import React from 'react' ;
import SearchList from './SearchList' ;
function App() {
return (
<div>
<SearchList />
</div>
);
}
export default App;
|
Javascript
import React, {
useState,
useTransition
} from 'react' ;
const namesList = [
'Alice' ,
'Bob' ,
'Charlie' ,
'David' ,
'Eva' ,
'Frank'
];
function SearchList() {
const [searchTerm, setSearchTerm] = useState( '' );
const [filteredNames, setFilteredNames] = useState(namesList);
const [isPending, setTransition] = useState();
const handleSearch = (e) => {
const term = e.target.value.toLowerCase();
setSearchTerm(term);
setTransition(() => {
const filtered =
namesList.filter(
name =>
name.toLowerCase()
.includes(term)
);
setFilteredNames(filtered);
})
};
return (
<div>
<label htmlFor= "search" >
Search:
</label>
<input
type= "text"
id= "search"
value={searchTerm}
onChange={handleSearch}
placeholder= "Type to search names" />
<ul>
{
filteredNames.map((name, index) => (
<li key={index}>
{name}
</li>
))
}
</ul>
</div>
);
}
export default SearchList;
|
Output:
useSyncExternalStore:
- React commonly uses internal states, but
useSyncExternalStore
comes into play when states are managed by third-party libraries or browser APIs outside React.
- This hook allows subscription to external stores, like global state in Redux or data in browser APIs (e.g., localStorage), ensuring components re-render upon changes in the external store.
Import:
import { useSyncExternalStore } from 'react'
Syntax:
const variable_name = useSyncExternalStore(subscribe, getSnapshot, [getServerSnapshot]?)
Example: below is the practical example of useSyncExternalStore hook
Javascript
import React from 'react' ;
import ResizableElement
from './BatteryStatusIndicator' ;
function App() {
return (
<div>
<ResizableElement />
</div>
);
}
export default App;
|
Javascript
import { useSyncExternalStore } from 'react'
export default function ResizableElement() {
const subscribe = (listener) => {
window.addEventListener( 'resize' , listener)
return () => {
window.removeEventListener( 'resize' , listener)
}
}
const width =
useSyncExternalStore(subscribe,
() => window.innerWidth);
return (
<div>
<p>Size: {width}</p>
</div>
)
}
|
Output:
Output
useInsertionEffect:
useEffect
executes a function after component rendering, while useInsertionEffect
is designed for inserting elements into the DOM before layout effects, like dynamic styles, without server rendering.
useInsertionEffect
is specialized for pre-layout element insertion, running only on the client side and not during server rendering.
Import:
import { useInsertionEffect } from 'react';
Syntax:
useInsertionEffect(()=>{
// Insert dynamic styles before layout effects fire
return()=>{
//cleanup function
}
}, [])
Example: This exampe implements UseInsertionEffectHook in React
Javascript
import React from 'react' ;
import UseInsertionEffectHook from './BatteryStatusIndicator' ;
function App() {
return (
<div>
<UseInsertionEffectHook/>
<br/>
<br/>
<button>First</button>
<button>Second</button>
</div>
);
}
export default App;
|
Javascript
import { useInsertionEffect, useState } from "react" ;
export default function UseInsertionEffectHook() {
const [theme, setTheme] = useState( 'dark' )
useInsertionEffect(() => {
const styleRule = getStyleRule(theme);
document.head.appendChild(styleRule);
return () => document.head.removeChild(styleRule)
}, [theme])
return <button
onClick={
() =>
setTheme(theme === 'dark' ?
'white' : 'dark' )}>
Change theme
</button>
}
const getStyleRule = (theme) => {
const tag = document.createElement( 'style' )
tag.innerHTML = `
button {
color: ${theme === 'dark' ? 'white' : 'black' };
background-color :
${theme === 'dark' ? 'black' : 'white' };
}
`
return tag
}
|
Output:
Output
Share your thoughts in the comments
Please Login to comment...