Разбор пытанняў з рэальных сумоўяў - React. Практыка.
Пытанне:
Якая будзе паслядоўнасць запісаў у кансолі?
text1import React, { Component, useEffect, useLayoutEffect } from 'react'; 2 3export const App = () => { 4 useEffect(() => console.log('useEffect'), []); 5 useLayoutEffect(() => console.log('useLayoutEffect'), []); 6 console.log('render'); 7 8 return null; 9};
Кароткі адказ:
text1> render 2> useLayoutEffect 3> useEffect
Па спасылцы можна запусціць код https://playcode.io/1373470.
Падрабязны адказ
Разглядзім спачатку, у чым розніца паміж 2 хукамі - useEffect і useLayoutEffect.
Розніца ў тым, што useLayoutEffect - працуе сінхронна (як і яго аналагі, хоць і не поўныя, - метады жыццевага цыклу класавых кампанентаў - componentDidMount і componentDidUpdate), а useEffect - асінхронна.
А калі так, то спачатку будзе выкананы ўвесь сінхронны код, а потым - асінхронны (тут варта ўспомніць, як працуе Event Loop).
Тады ўзнікае пытанне, чаму першым у кансолі з'яўляецца "render"?
Render - гэта абнаўленне React tree (якое раней называлі Virtual DOM), але гэта яшчэ не абнаўленне Real DOM і абнаўленне старонкі ў браўзеры.
Памятая пра гэта, атрымліваем наступны парадак:
text1> render -> useLayoutEffect -> адмалеўка змен на старонцы -> useEffect
На гэтым прыкладзе бачна, што useEffect спрацоўвае пасля адмалёўкі старонкі. То бок, калі useEffect змяняе, напрыклад, state, значэнне якога мы паказваем карыстальніку, то у гэтым выпадку мы ўбачым мільгаценне на экране - спачатку старога значэння state, а потым - адноўленага. Для пазбягання мільгацення і існуе useLayoutEffect.
Варта таксама памятаць, што пасля render могуць быць выкліканыя дадатковыя перарэндэры, калі ў нас, напрыклад, змяніўся state, альбо па іншым прычынам, і толькі затым адпрацуе useLayoutEffect:
text1> render -> useState -> re-render -> useLayoutEffect -> адмалёўка змен на старонцы -> useEffect
Дадаткова можна пачытаць:
Каментары
(Каб даслаць каментар залагуйцеся ў свой уліковы запіс)