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