Re render useLayoutEffect
У меня есть такой код:
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
import styles from './styles.module.css'
import { Header } from '../../../../modules/Header'
import RowRecomend from '../RowRecomend/RowRecomend'
import { ICard } from '../../../../components/Card/Card'
const HomeOutlet = () => {
const ref=useRef<HTMLDivElement>(null)
const [cards,setCards]=useState<ICard[]>([])
const [firstCalculating, setFirstCalculating]=useState<boolean>(true)
useLayoutEffect(()=>{
if(firstCalculating && ref.current){
const howCards=Math.floor(ref.current.clientWidth/178)
for(let i=0; i<howCards;i++){
setCards((prev)=>[...prev,{song:'Bank Account',artist:'21 savage',img:''}])
}
setFirstCalculating(false)
}
},[])
return (
<div className={styles.wrap} ref={ref}>
<Header/>
<RowRecomend title='Great first audiobooks' cards={cards}/>
<RowRecomend title='Что-то новенькое' cards={cards}/>
</div>
)
}
export default HomeOutlet
Я не понимаю почему у меня код внутри проверки в useLayoutEffect выполняется два раза, я знаю, что у меня стоит strict mode, но у меня есть ограничитель firstCalculating, даже если я поставлю в массив зависимостей firstCalculating, все равно будет выполняться два раза, даже если я сменю useLayoutEffect на useEffect.
Ответы (1 шт):
Автор решения: Oliver Patterson
→ Ссылка
Вам нужно создать ref что-то типо const isFristRenderRef = useRef<boolean>(true) и в useLayoutEffect проверять, если он false - делаем return, иначе мы выставляем для isFristRenderRef.current = false и делаем остальной код.
Итоговый код будет таким:
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import styles from './styles.module.css';
import { Header } from '../../../../modules/Header';
import RowRecomend from '../RowRecomend/RowRecomend';
import { ICard } from '../../../../components/Card/Card';
const HomeOutlet = () =>
{
const isFirstRenderRef = useRef<boolean>(true)
const ref = useRef<HTMLDivElement>(null);
const [ cards, setCards ] = useState<ICard[]>([]);
useLayoutEffect(() =>
{
if (ref.current === null || isFirstRenderRef.current === false)
{
return;
}
isFirstRenderRef.current = false;
const howCards = Math.floor(ref.current.clientWidth / 178);
for (let i = 0; i < howCards; i++)
{
setCards((prev) => [ ...prev, { song: 'Bank Account', artist: '21 savage', img: '' } ]);
}
}, []);
return (
<div className={styles.wrap} ref={ref}>
<Header />
<RowRecomend title='Great first audiobooks' cards={cards} />
<RowRecomend title='Что-то новенькое' cards={cards} />
</div>
);
};
export default HomeOutlet;