I'm planning to exclude this but just would like to double-check that there is no better way to do this.
Thus i plan to disable exhaustive-deps for this line.
Is this wise?
useEffect(() => {
async function handleViews() {
await sendViews(views, user, cancelToken);
... do more
}
if (
appStateVisible.match('inactive') ||
appStateVisible.match('background')
) {
handleViews();
}
}, [appStateVisible]);
No. You have a couple of solutions that are preferred to just ignore the rule.
You could provide a referentially stable value. I sometimes like to use a useGetter
sort of hook:
const useGetter = <S>(value: S): (() => S) => {
const ref = useRef(value);
useLayoutEffect(() => {
ref.current = value;
});
return useCallback(() => ref.current, [ref]);
};
which allow you to write something like:
const getViewData = useGetter({ user, cancelToken })
useEffect(() => {
async function handleViews() {
const { user, cancelToken } = getViewData()
const user = await sendViews(views, user, cancelToken);
... do more
}
if (
appStateVisible.match('inactive') ||
appStateVisible.match('background')
) {
handleViews();
}
}, [appStateVisible, getViewData]);
Because getViewData
don't change, the useEffect will not be triggered for any other reason than the change in the app state. And the return value will not be stale.
As an alternative, you could provide all the dependencies normally, but this time check if appStateVisible changed or not yourself. Hooks like usePrevious
that just refer to the previous value can be useful for checking that previousAppStateVisible !== undefined && appStateVisible !== previousAppStateVisible
the value changed from the last render. If not, you can return early. ( https://usehooks.com/usePrevious/ )