I have a simple React snippet which produces surprising console output in the browser:
import { useEffect, useState, useCallback } from "react";
export default function App() {
const [data, setData] = useState([]);
const [isFetching, setIsFetching] = useState(false);
const fetchData = useCallback(async () => {
if (isFetching) return;
setIsFetching(true);
console.log("fetch 1");
console.log("fetch 2");
try {
const response = await new Promise((resolve) => {
setTimeout(() => {
resolve(Math.floor(Math.random() * 10));
}, 10);
});
setData((prev) => [...prev, response]);
} finally {
setIsFetching(false);
console.log(`done 1`);
console.log(`done 2`);
}
}, [setData, isFetching]);
useEffect(() => {
window.addEventListener("scroll", fetchData);
return () => {
window.removeEventListener("scroll", fetchData);
};
}, [fetchData]);
return (
<div className="App">
<button
onClick={() => {
setData([]);
}}
>
Clear
</button>
<h1 className="Data">Data: {data}</h1>
</div>
);
}
When scrolling there is an uneven ratio of adjacent console.log prints, where you may see:
- fetch 1
- fetch 2
- fetch 2
- done 1
- done 2
or some combination where 5 or more statements appear to make up one function call.
While React itself is not desynchronized, the strange output caused me to worry about lifecycle bugs in a complex project. Not to mention clouding the logs so much that they lost readability.
Note:
- Refs do not help
- Throttling/debouncing does not help