You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
38 lines
955 B
38 lines
955 B
import { useEffect, useRef, useState } from "react";
|
|
|
|
export const useEffectOnce = (effect) => {
|
|
const effectFn = useRef(effect);
|
|
const destroyFn = useRef();
|
|
const effectCalled = useRef(false);
|
|
const rendered = useRef(false);
|
|
const [, setVal] = useState(0);
|
|
|
|
if (effectCalled.current) {
|
|
rendered.current = true;
|
|
}
|
|
|
|
useEffect(() => {
|
|
// only execute the effect first time around
|
|
if (!effectCalled.current) {
|
|
destroyFn.current = effectFn.current();
|
|
effectCalled.current = true;
|
|
}
|
|
|
|
// this forces one render after the effect is run
|
|
setVal((val) => val + 1);
|
|
|
|
return () => {
|
|
// if the comp didn't render since the useEffect was called,
|
|
// we know it's the dummy React cycle
|
|
if (!rendered.current) {
|
|
return;
|
|
}
|
|
|
|
// otherwise this is not a dummy destroy, so call the destroy func
|
|
if (destroyFn.current) {
|
|
destroyFn.current();
|
|
}
|
|
};
|
|
}, []);
|
|
};
|