Из документов :
Почему внутри функции отображается устаревший реквизит или состояние?
Любая функция внутри компонента, включая обработчики событий и эффекты, «видит» реквизит и состояние из рендера, в котором он был создан.
Бывает, что incrementState
определен внутри useRef
и, следовательно, только «видит» начальное состояние.
Если вы хотите исправить только одно состояние, это довольно просто:
const incrementState = () => {
setInd(prevInd => prevInd + 1);
}
Мы используем функциональную версию установщика состояний , так что мы не будем Не пропустите никаких обновлений о состоянии.
Но что, если этот обработчик фактически зависит от другой переменной состояния?
const observer = useRef();
// Adding a placeholder state for demo
const [secondState, setSecondState] = useState();
useEffect(() => {
const incrementState = () => {
// something to do with second state here
if(secondState)
setInd(prevInd => prevInd + 1);
};
observer.current = new IntersectionObserver(
entries => {
const first = entries[0];
if (first.isIntersecting) {
incrementState();
}
},
{ threshold: 1 }
);
}, [secondState]); // note dependency here, ensures that each updates "sees" the new version of function
useEffect(() => {
// observer and so on...
});
const { Component, useRef, useState, useEffect } = React;
const { render } = ReactDOM;
function App() {
const thingRef = useRef();
const [count, setCount] = useState(0);
const incrementCounter = () => {
setCount(prevCount => prevCount + 1);
};
const observer = useRef(
new IntersectionObserver(
entries => {
const first = entries[0];
if (first.isIntersecting) {
incrementCounter();
}
},
{ threshold: 1 }
)
);
useEffect(() => {
const currentElement = thingRef.current;
const currentObserver = observer.current;
if (currentElement) {
currentObserver.observe(currentElement);
}
return () => {
if (currentElement) {
currentObserver.unobserve(currentElement);
}
};
}, []);
return (
<main style={{ height: "600vh", position: "relative" }}>
<div
ref={thingRef}
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
height: '80vh',
border: '1px solid pink',
width: '98%',
textAlign: 'center',
}}
>
Thing
</div>
<p
style={{
backgroundColor: 'red',
borderRadius: '50%',
color: 'white',
width: '20px',
height: '20px',
lineHeight: '20px',
textAlign: 'center',
position: 'fixed',
top: '10px',
right: '80px',
margin: 0
}}
>{count}</p>
</main>
);
}
render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root" />