In a React app we are debouncing the keyboard input before performing a search similar to this simplified example:
function App() {
const inputRef = useRef();
const [result, setResult] = useState();
const timeout = useRef();
useEffect(() => () => clearTimeout(timeout.current));
const debouncedSearch = useCallback((text) => {
clearTimeout(timeout.current);
const p = new Promise((resolve, reject) => {
timeout.current = setTimeout(async () => {
const result = await axios.get("/search?q=" + text);
resolve(result);
}, 1500);
});
return p;
}, []);
const onChange = useCallback(() => {
const fn = async () => {
const result = await debouncedSearch(inputRef.current.value);
//if the promise isn't fulfilled will this hold onto setResult?
setResult(result);
};
fn();
}, []);
return (
<div>
<input ref={inputRef} onChange={onChange} />
<div>{result}</div>
</div>
);
}
As you can see for every letter typed, in onChange
we are creating a new Promise and discarding the previous handler if called within 1.5 seconds.
Since the previous Promises are created but their state remains as unfulfilled, will they hold a hard reference to setResult
which also holds a preference to previous render states, which leaks memory?