Почему хук вызывается 2 раза?
Имеется такой код:
function MainPage() {
let slider = React.createRef();
let slideSpeed = 500;
let [slidesCount, setSlidesCount] = useState(0);
let [leftDragger, setLeftDragger] = useState(0);
let [activeSlide, setActiveSlide] = useState(0);
//Хук вызывается 2 раза
useEffect(() => {
setSlidesCount(document.querySelectorAll('.slick-list .slick-slide:not(.slick-cloned)').length)
console.log(slidesCount) //Сначала выводит 0, потом 4
}, [slidesCount]);
let settings = {
dots: false,
infinite: true,
speed: slideSpeed,
slidesToShow: 1,
slidesToScroll: 1,
arrows: false,
beforeChange: (currentSlide, nextSlide) => {
setActiveSlide(nextSlide);
console.log(leftDragger);
if(activeSlide == 0) {
setLeftDragger(100 / slidesCount * (activeSlide + 1) / 2 + "%");
} else {
setLeftDragger(20)
}
}
};
return(
<div className="main-page">
<section className="about">
<Slider ref={slider} {...settings}>
</Slider>
<SliderNav slideSpeed={slideSpeed} sliderDOM={slider} />
</section>
<section className="remembers">
</section>
</div>
)
}
export default MainPage;
useEffect вызывается 2 раза, сначала выводит 0 элементов (хотя их 4), а второй раз уже 4, почему так происходит и как это исправить?
Ответы (1 шт):
useEffect сначала срабатывает на дефолтном значении, определенном в let [foo, setFoo] = useState(0);.
useEffect сработал, запустилось setFoo(4); console.log(foo);. setFoo(4) меняет значение асинхронно, так что получаем вывод console.log(foo); // 0;
useEffect вызывается при изменении foo. А значит как только обновится foo оно вызовется снова.
setFoo(4) отработал и изменил значение foo. Снова срабатывает useEffect.
Еще раз выполняется setFoo(4), только на этот раз значение и так уже было 4. В консоли соответственно 4. Значение не изменилось, useEffect больше не выполняется.
Упрощенный ваш пример:
const { useState } = React;
function MainPage() {
let [foo, setFoo] = useState(0);
React.useEffect(() => {
setFoo(4)
console.log(foo) //Сначала выводит 0, потом 4
}, [foo]);
return(<div className="main-page"/>)
}
ReactDOM.render(<MainPage/>, document.getElementById('app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
Лучше не менять состояние в useEffect, если он с ним связан.
Вот пример:
const { useState } = React;
function MainPage() {
let [foo, setFoo] = useState(0);
React.useEffect(() => {});
React.useEffect(() => {
setFoo(foo + (foo < 100))
console.log(foo)
}, [foo]);
return(<div className="main-page"/>)
}
ReactDOM.render(<MainPage/>, document.getElementById('app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
