Search⌘ K
AI Features

React Side-Effects

Explore how to use React's useEffect Hook to manage side-effects like syncing the search term with browser local storage. Understand dependency arrays and how to cleanly separate side-effect logic from state updates for robust React apps.

We'll cover the following...

We’ll make the Search component remember the most recent search interaction, so the application opens it in the browser whenever it restarts.

First, use the local storage of the browser to store the searchTerm accompanied by an identifier. Next, use the stored value, if a value exists, to set the initial state of the searchTerm. Otherwise, the initial state defaults to our initial state (here “React”) as before:

Node.js
const App = () => {
...
const [searchTerm, setSearchTerm] = React.useState(
localStorage.getItem('search') || 'React'
);
const handleSearch = event => {
setSearchTerm(event.target.value);
localStorage.setItem('search', event.target.value);
};
...
);
~~

When using the input field and refreshing the browser tab, the browser should remember the latest search term. Using the local storage in React can be seen as a side-effect because we interact outside of React’s domain by using the browser’s API.

There is one flaw, though. The handler function should mostly be concerned about updating the state, but now it has a side-effect. If we use the setSearchTerm function elsewhere in our application, we will break the feature we implemented because we can’t be sure the local storage will also get updated.

To fix this, we handle the side-effect at a dedicated place using React’s useEffect Hook. This hook is essential for managing the React component lifecycle in functional components.

Node.js
const App = () => {
...
const [searchTerm, setSearchTerm] = React.useState(
localStorage.getItem('search') || 'React'
);
React.useEffect(() => {
localStorage.setItem('search', searchTerm);
}, [searchTerm]);
const handleSearch = event => {
setSearchTerm(event.target.value);
};
...
);

React’s useEffect Hook takes two arguments:

  • The first argument is a function where the side-effect occurs. In our case, the side-effect is when the user types the searchTerm into the browser’s local storage.
  • The second argument is a dependency array of variables. If one variable changes, the function for the side-effect is called. In our case, the function is called every time the searchTerm changes; it’s called initially when the component renders for the first time.

If the dependency array of React’s useEffect is an empty array, the function for the side-effect is only called once, after the component renders for the first time. The hook lets us opt into React’s component lifecycle. It can be triggered when the component is first mounted, but also one of its dependencies are updated.

Using React useEffect instead of managing the side-effect in the handler has made the application more robust. Whenever and wherever searchTerm is updated via setSearchTerm, local storage will always be in sync with it.

📜 Check the persistence by opening the app link in a tab, changing the search term, closing the tab, reopening the app link. Note that the session is live for only 30 minutes. After this the server restarts.

 ãF )   95@@ °n‰PNG


IHDR(-SäPLTE""""""""""""""""""2PX=r€)7;*:>H¤-BGEˆš8do5Xb6[eK™®Kš¯1MU9gs3S\I“§:gt'03@{‹V¹ÔT´ÏA}V»Ö@y‰6\fH’¦-CII”¨Eˆ›+;@7_i7_jFŠJ–«K›°H£-BHaÚû,@FCƒ”L³&.0W½ÙN£ºI“¨$)+B‘J•ªR¯È?v†>s>u„S±Ê=qP©ÁP¨ÀP§¿,?D4U^%+-M ¶K˜®%+,2OX+<ALœ²#&&D†˜%,.I•©vôTötRNSIæçJäeÀe¦©IDATxM޵ZEA„ÿÙ³	îî%R¡ïßáTThÇG…»,Á®Å=²Òîmífímnf’A–$â‡>!¦gºôHg½Eߏܵ}	Ý»ý‡º¼kdú§¯Jo—™Î3æL"J¹ ›ÌÕüQ‡$âçļffµ,é€5i9̟¯H¨/mB†‡wÍÜw;D
Ø+&‚W«ª¹¨Dôo@Ê´RI©ÐB¡om.Û³ÀIEND®B`‚‰PNG


IHDRשÍÊePLTE""""""""""""""""""""""""2RZN¢¹J–«3R[J—¬)59YÁÞ0KS4W`Q«ÄLœ²%+-0JR)6::gtC‚“"##?v†U·Ñ?w†<n{&-/YÂß=q:iuBA}A{ŒB‘/IPP§¿=q€K™®_ÔóL³$();lzR¯ÉaÚûI“¨ZÆã3U^1MU3T]ZÅâI“§X¿ÜF‹ž-BGP¨À6[e,@E5ZdO§¿-BHX¿Û+=AW¾Ú,@FW¼ØQªÃ?v…W¼×+<A@yˆ"#$\Ìê4Wa\ÌëS²Ì$(*.EL^ÑñVºÕ6]h#$%GŽ¡#&';jwV¹Ô-CIL›±ZÄá^Ðï>u„S°Ê/HNM ·_Õõ\ËéM ¶8doD…—D†˜>tƒ+=B[Èæ,>C>t‚<o}@y‰0LS.EKT´Î$'(%,.A~ŽW½ÙC’%+,\ÊèC!ätRNS‘í‰œG¾ÖOIDATxl‰ÃB¶Q…Ÿu´ß_ȳ<˦Ýveê²óa6AξŒûv¢{@ÎE'ÞdIÕ!çží ðC—ÔT‹þg1ÂE(ÏñSQsâi
ď…Zÿ·V¹Ð)ég!‰ªhÎùtéº-i}˜µµ<Õ?¶lBZaÄ´4{DÓ⌻_e8¥yǁ­À3ž)Ÿ¥?°f;8.ã¤tÌ=å;	:ã52fKZìlù¨ØšÍ9.ž#ƒÒAÁqÌúÛ®£Vÿ`=$¬Â?_¶¾®ÔqMç.ïJ$
?^q÷ñíۏï.},‚ìsæÝ_TttÔ¾1#‰/(ì—-[è`è`ÌÚïÅðZd5’Ž™›?ÎebZ¿Þˆi.Ûæ™ìq΄+1°}Œ5ùïçd¨G•ÏøIEND®B`‚‰PNG


IHDR  D¤ŠÆAPLTE"""""""""""""""""""""""""""2RZVºÖ_ÔôU·Ñ=r€$()'25]ÎíCƒ•0LS<o}XÀÜX¿Û0JQ=p~D„–<n{VºÕE‡™8do_ÔóEˆšF‹žH‘¥9dp_ÕõH¤I“¨FŒŸ6[e`Ö÷`×øL³/GM_ÓòU¸Ó'02P©Á/IPPªÂX¿Ü&/1;ly3R[`ØøGŽ¡T³Í\ÌêaÚû1OW"##Q«ÄaÙúR®Ç=q€`Öö.EL+=ATµÐ-CIK˜®#&'C‚“^ÐïI”¨&.04U^^Ñð@yˆZÇä$(*[Éç^Ññ,?DR¯É"#$1NV1MTD…—>u„;kxG R¯È/HN&-/@y‰>s>t‚@zŠ]ÍìP¨À$'(D†—]Ïî<n|0JRU·Ò×\¼	tRNS%­ñ'ïó(ò~ÑÝèžIDATx“šC1F_Ý¿MmÛ¶4¶m{ÿ˜¤n†çáÓ	®A$–à$b‘ Heø™TãWÄÂh•šh´:PtZ
Q«0@.`€Þ`4™-V`³Zì&‡A#ÁébkÝÄãñúØ>.''ø`C$FØÏ	‘(±x"6Xác”TÚéL§@Iù;dd-¹|¾P,Ȕ9¡R­ÕÍf3¢¿F½VmMíX§ÚíÍç@Y˜7ÎõºÕN¬=—ŽåÈʪu
}Ö¬«+‘e‡aiq ¤Ö76­íÝ=h
ûZìíîl›ë‡}á¨ʱ¥[F«I9A¹k9¥ÖëäŒ3¢Ã9ΡóžqB~Øáb¸ÃåU_¸^Ü[·ôw†ý{z‡v‡z‡Ù(Š£(Š£(þ›†Šfòq”ÉG–Éïkñ”ÏçŠY¾ÿªfäòÇ~à:*4ÓQ\O>Ÿ‘ ‡¼<דúW£éÍZ|ދÅ7“ñ•ïjTÔäãn”½»¢®`$Hð+ò¿GOñûð*èx‹•ø¥X*|”^ÿdIEND®B`‚‰PNG


IHDR@@·ì:PLTE"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""%+-@y‰W¼×`×ø^ÑñS²ÌC‚“,>C*8<XÁÝaÚûaÙùMŸµ+<AaÙúXÀÜ#%%TµÐLž´=q>u„K›°`ÖöA}L›±8do=r€%+,@yˆ^ÐïS²Ë)59=q€P©ÁU·Ò"#$PªÂ\Êè0JQQªÃ"##U·Ñ#&&_Ôô>t‚>s`Øø_Ôó5Yc1OW5Zd1NV+=B1MU+;@/GM\Ìê*;?3S\)8<2RZ_Õõ+=A]Ïî,@F,@E&-/0KS7alO¦¾9dp8amB~EˆšP¨ÀN¢¹'023T]]Îí?x‡3U^Cƒ•6\gU¸Ó&.0D„–7_iR­ÆH‘¥I”¨M ¶$(*?v…ZÆãX¿Ü-AG#$%[Éç8co[ÈæW½ÙC’'25?v†8bn%*+Lœ²N£º2PX)7;=p~(58^ÒòP§¿4WaQ«ÄT´Ï0JRQ¬ÅT´ÎI“¨6]hR¯ÉT³Í0LSF‹9eqEˆ›E‰œ9gsFŠCƒ”#&'\Ëé`Ö÷&/16\fB‘A{ŒR®Ç]Íì(47%,.*:>*9=9fr:gt7^iU¶Ð?w†ZÇäX¿Û^ÑðQ­ÅH£)6:V¹Ô'034U^E‡™.EL.FMK™®@zŠS×tRNS*Ž×øÖ”ý˜	»½•+üùóԐ,ØúôÀ=VIDATx¤ËµC!Ð‡C|ÿãÚ^yR]ÕMÛáO]ßÔÕÝ0NÈ2ÍËí¿"ªª¢(0Vã(ÀY%PDT-~(m¬ó!âKÞY£~´•üIÒf{³ÛÞáa¼§§ô3—ÕOp&”Ф‰¡xŽ÷#Ÿj­ôÚ¶mméòc)]m¤’‡É)Ƨgfçhk²ñÎÒ ægg¦Ç™šìÐ+X€ÅêuiyVת·k«°²\[ü:,Ø6ØÜjIJ
;»"»;°×XùþÛfÁáÇÍûý“SÎÎÏÏ8=Þo¾;æèÐ(ƒ‹öÓ¥BkÔeûÍ\7p+mîîáþNÚ<ÀQðOÒæùô³´y‚g»ttÐëo•ý½£ŸìVð»Òäsýü¬™ø”&_ðaüïV~à·Ö?­*8àQ ;8¥Á,¸¤‚f¥“1Üx¤†×§ñŸ*œøÑA¯Ôð°a#±³¶¦#ŠnP‘i+¼¶CÈ,ˆÆèäÍ_áNbÑá‚øç•HŽB*ÚÒ¦ L(^<ñÁ‚L6pJ¾P”ɥީ¢%"“R,ä9Èe3eRËa1(
¢ßqÇ8َ´ŠmK˱mƶmÛü·yi!èΪYÏuë ÀÏ_Àï?i÷ˆý+òŠÄA|ù{‘˜´?¿_En).JËD¤<€
©¬¢Z\Ts©R*(	¯©JŠ…uX/
4J9š¡5·DEµ4kÇ4‡&i¥V4Ú¡®Ð¯†vsf:àg,¢èBC»î$¶ºÍùá–@ôŠI_?<‘!^ŠÈàÓ½ÇöäõB‘%Làw±FD1ŠÁ¨(F€±øH˜%0Ʊ¿Å؄(¢0ˆÅÄ'Åæ—N.0u„@íY‡PWìIüaNâKš™Ä?ðÓµŒ=Žeœv/c—±ŒÓ0c0÷2Êë:ˆ06R-uÒÄ­\Q̶ää´¼µ6R#
ÆFš³6Òñ·rՁ­ìu˜æmâðž‡Iñi~ –Åü ÃsPþ"±óŸ¼
eiyå£ËPšàãÊò’§¡œÝÒ,S]U¦ºV…ªÖ”©®Z¦êoëë·xzã™âÆSnm¬{ÚºwaلÏ…Å»´Ýõ(mg/®þå½À¿¼ûŒ[§b³µq¶Å&Õ¯¹$ñzȊ‹H>aÌKT1/æø1O‚‰0¾.h͇YþAÓö£
-ê>ۋº«¢XÕ¢î}ߨëÛÑ;ÃöN´ØvÅýÎ¸ÿ1ë×ÄO@&v/Äþ_—ö\ôÇ\í.™½+0”;!fÊ¦´Ó% JY·O”ÂŽ'/Å]_Š;ßÀ'"&Nªn	aQ^”cx¦AáÒIEND®B`‚

Exercises:

  • Confirm the changes from the last section.
  • Read more about React’s useEffect Hook ([0], [1]).
  • Give the first argument’s function a console.log() and experiment with React’s useEffect Hook’s dependency array. Check the logs for an empty dependency array too.