Follow us

React 18 - Features & Enhancements

React 18 is being release to Public soon early next year(may be Jan 2022) and having lots of exciting features and enhancement which you must be knowing, so that you should start using them.

 

useId()

  • "React.useId()", provide unique value per component in your app.
  • If you use same value assigned to variable, will give you same value.
  • By using multiple times "React.useId()", each time it will give you unique value per component.
  • It is unique per component only, with other component, value might be same.

Demo: With below example, I used same useId() value for firstName and lastName label and different for email and submit button. So for firstName and lastName will have same id value and for email and submit button, will have different id value.

React. useld(); 
const id2 = React. useld()• 
e o initialize ALL of fields with values. 
const for-mik = 
return ( 
<form 
< label + 
< input 
< Ia&el 
< input 
. values . firstName 
{id + 
values . lastName} 
< label + Address 
< / label > 
values . email) 
(button + 
< / button>

Result:

G) localhost:3000/SignupForm 
ea er area. 
Hame I UserFarm I SignupForm+Userld I Listltems+Batching I SuspenseListltems I 
SuspenseDemoFakeData I ListltemFiIter-UseTransitian I I ConcurrentListUsers- 
UseTransition I UserDetails & Add I BatchingFunEventState I UseSyncExternalStare I 
App component load. 
Demo: "React.useld()", provide unique id per component in your app. 
If you use same value assigned to variable, will give you same value. 
By multiple times " React.useld()", each time it will give you unique value per component. 
It is unique per component only, with other component, value might be same. 
Submit 
Elements Console Sources 
Components 
(form 
<label >First 
Networl 
<input ame" valu 
url ( " ta : image ; base", iVBORvMGgoAAAANSlJhELlgAAA8Aß 
%uNcuZd6x1AFeZ6fGCdJ8kY4y7uuTRNCd7iyESXsd0PE3aøQGPsni 
ayz01F2qyBuKKbcogPXdVeY9rwgNsjfgccYesJhk3fSdYTIHX9gRØL 
JRaAmEAaumPaM/rRehyK'hXqbFAA9kh3/8/NvHxÅY6AsZ/i181a1kCLE 
ackground-repeat: no- repeat; background-attachment: scr 
18px; background-position: 5B; cursor: auto; ' 
<label 
(input id=" lastNane•• value) 
< label >EmaiI 
<input 
value> 
<button Submit</button) 
fornl>

 

 

Batching:

  • Batching for fewer renders. Groups multiple state updates into a single re-render for better performance.
  • With below demo, auto batching applied due to react 18 upgrade. You can check the console log where having one time render only, even I have two state update on button click inside promise.
  • But, if you want to load/render on each state update then you can use "flushSync". Refer below second demo.
  • One time render was already there but simple button click event, you can refer below third demo. With react 18 now it enabled even inside promise, settimeout etc.

Demo 1:

import React, { useState } fran "react"; 
import { flushSync } from "react-dom"; 
is 11 You ml_ßt be kidding 
export const BatchingFunEventState = () 
const [count, setCount] = useState(e); 
const [flag, setFIag] = useState(faIse); 
//// Note - One time render only even there is tw state being update inside prom 
Complexity is is cool! 
handleCIick() { 
function 
conso 
= click = 
fetchS0Rthing() . { 
// React 18 with createRoot bat es these: 
setCount((c) c + I); 
not re-render yet 
setFIag( (f) 
! f); // [hes ot re-render yet 
// React will only re-re er once at the end (that's batching!) 
return ( 
(button 
style= color: flag . 
<LogEvents / > 
< / div > 
function LogEvent 
props) 
- -Render---"); 
console . log 
Next (check console, render 
"blue" • "black" 
ret urn 
function 
ret urn 
null; 
is 3 is col! 
fetchSomething() { 
new 
setTimeout(resoIve, 
1%));

Result:

C localhost:3000/8atchingFunEventState 
eader 
Hame I UserFarm I SignupForm+Userld() I Listltems+Batching I SuspenseListltems I 
SuspenseDemoFakeData I ListltemFiIter-UseTransitian I I ConcurrentListUsers- 
UseTransition I UserDetails & Add I BatchingFunEventState I UseSyncExternalStore I 
App component load. 
Next (check console, render output) 
1 
Elements Console 
top @ Filter 
click 
- -Render 
-Render---

 

Demo 2: use flushSync to avoid batching:

// uote - if I don't want to batch% 
Complexity is 6 It's time to do somethirv„ 
handleCIick() 
function 
click = 
S Everything is 
fetchS0Rthing() . { 
setCount((c) 
// React has updated the 00M by nch•' 
setFIag( (f) If) 
// React has updated the 00M by nch•' 
use flushSync

Result:

C localhost:3000/8atchingFunEventState 
Hame I UserFarm I SignupForm+Userld() I Listltems+Batching I SuspenseListltems I 
SuspenseDemoFakeData I ListltemFiIter-UseTransitian I I ConcurrentListUsers- 
UseTransition I UserDetails & Add I BatchingFunEventState I UseSyncExternalStare I 
App component load. 
Next (check console, render output) 
1 
Elements Console 
top @ Filter 
click 
-Render-- 
-Render-- 
-Render --- 
-Render---

 

 

Suspense:

  • "Suspense" give you option to partially load UI instead of waiting for complete content to fetch and load.
  • We were already doing this by controlling/writing-code self like checking fetch/load endpoint status(refer "ListItems+Batching" menu for this).
  • But now we can simply use "Suspense" for that loading component and it will do all for you.
  • With this example, I have some static content as you can see on the same page along with below section it is actually fetching endpoint to load list.
  • With Suspense, its easy to manage at one place with less line of code.

 

C localhost:3000/SuspenseListltems 
IS ea er area. 
ame I UserFarm I SignupForm+Userld I Listltems+Batching I SuspenseListltems I 
uspenseDemoFakeData I ListltemFiIter-UseTransitian I I ConcurrentListUsers-UseTransition I 
serDetails & Add I BatchingFunEventState I UseSyncExternalStore I TestDema 
App component load. 
Demo: "Suspense" give you option to partially load UI instead of waiting for complete content 
o fetch and load. 
e were already doing this by controlling/writing-code self like checking fetch/load endpoint 
status(refer "Listltems+aatching" menu for this). 
But now we can simply use 'Suspense" for that loading component and it will do all for you. 
ith this example, I have some static content as you are reading currently which got already 
loaded and with below section it is actually fetting endpoint to load list. 
ith Suspense, its easy to manage at one place wiht less line of code. 
Loading...

After few second, content loaded:

C localhost:3000/SuspenseListltems 
IS IS e er area. 
Hame I UserForm I SignupForm+Userld I Listltems+Batching I SuspenseListltems I 
SuspenseDemoFakeData I ListltemFiIter-UseTransitian I I ConcurrentListUsers-UseTransiti( 
UserDetails & Add I BatchingFunEventState I UseSyncExternalStore I TestDema 
App component load. 
Demo: "Suspense" give you option to partially load UI instead of waiting for complete co 
o fetch and load. 
e were already doing this by controlling/writing-code self like checking fetch/load endF 
status(refer "Listltems+aatching" menu for this). 
But now we can simply use 'Suspense" for that loading component and it will do all for y 
ith this example, I have some static content as you are reading currently which got alre 
loaded and with below section it is actually fetting endpoint to load list. 
ith Sus ense, its easy to manage at one place wiht less line of code. 
Leanne Graham I Sincere@a .biz 
Ervin Howell I Shanna@melissa.tv 
Clementine gauch I Nathan@yesenia.net 
Patricia Lebsack I Julianne.OConner@kory.org

 

To use "Suspense" in code, refer below:

We simply need to put data fetching/loading component inside Suspense with fallback.

export default function SuspenseListItems() 
return ( 
<React . Suspense 
style= 
< Listltems / > 
React. Suspense> 
{ background: 
"yellow

 

Concurrent Rending, useTransition():

  • Sometimes, small actions like clicking a button or typing into an input can cause a lot to happen on screen. This can cause the page to freeze or hang while all of the work is being done. This new API improve user interactions by marking specific updates as “transitions”. Provide visual feedback during a state transition and keep the browser responsive while a transition is happening.
  • With below demo, without using "startTransition()", on button click, list will be reloaded and for moment you will see empty area in place of list items.
  • But if you will use "startTransition()", then it will show previous list items until it pull new content on button click.
  • useTransition() also provide isPending prop and value is true while the transition is pending and this allowing you to show an inline spinner.

Demo: with startTransition(), where I am loading endpoint data into set state and then same state sending to list component to render content along with isPending prop.

const CisPending, startTransition] - 
timeoutMs: 
useEffect(() 
const handleNameSearchInput = 
Complexity is 3 is cool! 
function handleCIick() 
setCount((c) 
(event ) 
setNameSearchFiIter (nanæSearch ) ; 
/ * *Note: if you enable below line instead of just below startTransition, 
eateUsersResource()); 
start 
// Transition: Show the results 
setUsersResource( createUsersResource() ) ; 
return ( 
Name Search: 
<input 
. useld() + "-searchText") 
then 
<button To Search & Increment Count</button) 
<table width: "10"" 
(React. Suspense . 
search 
< (React . Suspense)

 

export default function resource, pending, searchText 
let items = 
resource . read(); 
if (searchText && searchText " 
" + searchText); 
console. . 
items = items. filter ( (item) 
item.name searchText); 
return ( 
<div 
nding 
background : 
minH eight 
: "e.2v 
"yellow" 
• "transparent", 
{items. map( (item, index) ( 
(div key={index}> 
{it&. name) I {item. email}

Result: as I have used "startTransition()", so my list area still show items and background is yellow because of isPending until it finish the rendering:

C G) localhost:3000/ConcurrentListlJsers 
IS IS ea er area. 
Hame I UserForm I SignupForm+Userld I Listltems+Batching I SuspenseLis 
SuspenseDemoFakeData I ListltemFiIter-UseTransitian I ConcurrentListUsers 
UserDetails & Add I BatchingFunEventState I UseSyncExternalStore I TestDer 
App component load. 
ame 
Click To Search & Increment Count 
Count : 2 
#test 1 
:test 1 
'test 1 
:test 1 
:test 1 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com

 

Now with this same example, if I just remove "useTransition()" from button click, then on button click, for moment, list area will show empty:

C localhost:3000/ConcurrentListlJsers 
ea er area. 
ome I UserForm I SignupForm+Userld I Listltems+Batching I SuspenseLis 
spenseDemoFakeData I ListltemFiIter-UseTransitian I ConcurrentListUsers- 
serDetails & Add I BatchingFunEventState I UseSyncExternalStore I TestDer 
App component load. 
Name 
Click To Search & Increment Count 
Count : 1 
Loading

 

One more relevant use I found by using "startTransition()" or "useDeferredValue()". You will find less no. of times data fetch and rending. Like with below example, I have input change event on textbox search, so that means on each character typing, it go for fetch api call and render UI:

C O localhost:3000/ListltemFilter 
IS IS e er area. 
Hame I UserFarm I SignupForm+Userld I Listltems+Batching, I 
SuspenseListltems I SuspenseDemoFakeData I ListltemFilter- 
UseTransition I ConcurrentListUsers-UseTransitian I UserDetails & 
Add [BatchingFunEventState I UseSyncExternalStore'TestDemo 
App component load. 
Name Search: 
Elem ents Console 
top @ Filter 
Render. 
Renter. 
searchlnput 
: test 
Result items : 
Render . 
Renter. 
searchlnput 
: test 
Result items : 
Render. 
Renter. 
searchlnput 
: test 
Result items : 
(4øøe) [fm}, 
Sources 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
• test 1 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
a52@a.cam 
IS is footer area.

 

Now with this same example, I created new state prop for filter value and passed that for search filter and this help to avoid having rendering on each character input:

const 
namesearcn, 
earcnj 
const [nameSearchFiIter, setNameSearchFiIter] - 
useState("" ; 
const [isPending, startTransition] = useTransition(); 
const = (event) { 
setNærSearch(event .target .value) ; 
state u dates inside as transitions 
// Transition: Show the results 
setNaneSearchFiIter(event. target. value ) ; 
/setNameSearchFiIter event. target . value); 
const differedNameSearch = React.useDeferredVaIue(naneSearch, 
// console. log( "differedNameSearch: ' 
differedNameSearch) ; 
return ( 
< div > 
Name " 
(input 
type= "text " 
value = {nansearch) 
timeoutms: 2' 
< div > 
{isPending 
< L istltems 
Loading filter search...

 

C O localhost:3000/ListltemFilter 
ea er area. 
Hame I UserFarm I SignupForm+Userld I Listltems+Batching, I 
ü1spenseListltems I SuspenseDemoFakeData I ListltemFilter- 
-JseTransition I ConcurrentListUsers-UseTransitian I UserDetails & 
tate I UseSyncExter 
App component load. 
Name Search: 
Elem ents 
top 
Renter 
Render . 
Renter. 
Render . 
Renter. 
searchlnput 
: test 
Result items : 
Render. 
Renter. 
searchlnput 
: test 
Result items : 
Render. 
Renter. 
Console 
Filter 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
test 1 
• test 1 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
I a52@a.com 
a52 a.cam 
rhis is footer area.

 

 

useAsyncExternalStore():

  • useAsyncExternalStore is replacement of (useMutableSource)
  • Due to concurrent rendering, any subscription based event/store, we should use "useAsyncExternalStore()" to sync Realtime value.

 

Demo:

import React, { useSyncExternaIStore } from 
Complexity is 3 is cæl! 
const subscribe = (notify) { 
window. notify); 
return ( ) 
"react"; 
windcx. notify); 
const getSnapshot = () innerUidth; 
function useWindowInnerWidth(serverFaIIback) { 
return useSyncExternaIStore(subscribe, getSnapshot, sem'erFaIIback); 
// return Reac . useMutabIeSource(serverFaIi6åZVl getSnapshot, subscribe) ; 
Complexity is g It's to do 
ExternalStore() 
export default function 
const width = useWindowInnerWidth(); 
// const width = getSnapshot(); 
return ( 
Replacement of 
Start resizing screen to see result 
Screen width:

 

 

React 18 Installation:

  • Currently as on today(21-Dec02021), React 18 is available RC(Release to Candidate) and hopping by early next year(may be Jan 2022), this will be available as release to Public. You can find more about release plan discussion with: https://github.com/reactwg/react-18/discussions/9
  • To use react 18 RC with your existing app, use below command to update:

npm install react@rc react-dom@rc

  • Post this, your need to replace index.jx DOM render to concurrent mode i.e.:

pp.js 1 
index-js > 
Hea 
ingort frcgn " . ,'A.pp"; 
import * as from 
" . 'serviceWorker"; 
-Before--------------*/ 
// Reacto•om. render( 
/ / < React . StrictMode) 
(App 
/ / U React . StrictMode>, 
/ / document . getEIementSyId( ' root ' ) 
--11% (React 18)------- 
const container = ; 
const root = 
root . render( 
(React . Strictmode> 
<App / > 
React. Strictmode>

Categories/Tags: react 18

Recent Articles

1

AWS Saving Plan - Cost optimization tips

2
3

AWS RDS Key Concepts & Why you should use it?

4
5

Open-Search/Kibana - Multi Tenancy Setup

See All Articles