Почему сброс эффекта из предыдущего компонента происходит позже начала рендера нового
Имею крайне простую структуру из компонента контейнера и двух вложенных компонентов, которые показываются по условию внутри контейнера.
Сам контейнер.
function List() {
const [isListVisible, setIsListVisible] = useState<boolean>(false);
console.log('List render start', isListVisible);
const toggle = () => {
setIsListVisible(!isListVisible);
}
return (
<div>
{ isListVisible && <Item /> }
{ !isListVisible && <AltItem /> }
<button onClick={toggle}>Toggle</button>
</div>
);
}
И два вложенных (полностью одинаковые, только названия разные).
export const Item = () => {
console.log('Item render start');
useEffect(() => {
console.log('Item effect start');
return () => {
console.log('Item effect cleanup');
}
},[]);
return (
<div>Item</div>
);
}
export const AltItem = () => {
console.log('AltItem render start');
useEffect(() => {
console.log(' AltItem effect start');
return () => {
console.log(' AltItem effect cleanup');
}
},[]);
return (
<div>AltItem</div>
);
}
Нажимая на кнопку Toggle мы размонтируем один компонент и монтируем другой. И в консоли лог следующего содержания :
List render start false
AltItem render start
Item effect cleanup
AltItem effect start
Т.е. логично предположить, что если isListVisible в значении fasle, то сначала должен размонтироваться Item и сработать сброс его эффекта, а после этого на это место смонтироваться AltItem. Но судя по логу происходит наоборот. Сначала начинает рендериться AltItem и только после этого срабатывает сброс эффекта Item.
Иначе говоря - почему лог вот такой
List render start false
AltItem render start
Item effect cleanup
AltItem effect start
а не вот такой -
List render start false
Item effect cleanup
AltItem render start
AltItem effect start
?
Ответы (1 шт):
Потому что запись render у тебя выводится не при обновлении dom, а при вызове функции. До того, как она вызвана, невозможно определить, остался компонент на месте или нет, а значит до неё вызывать очистку нельзя. По крайней мере, если считать, что сначала формируется виртуальный dom, а потом он сопоставляется с предыдущим, а это вроде реакт гарантирует.