I'm planning to exclude this but just would like to double-check that there is no better way to do this.
- This logic detects that the user has moved the app to the background (via appstatevisible) and then sends a bunch of data (views) to the server.
- eslint recommends including views, users, cancelToken into the dependency array but it doesn't make sense as I only want to send this based on the appStateVisible. I do not want to trigger this every time the user or views eg is updated.
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]);
CodePudding user response:
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/ )