Skip to content

Instantly share code, notes, and snippets.

@wheelo
Forked from justblender/useAppSelector.ts
Created March 24, 2022 10:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wheelo/0e2d59fd303c6f4146477d675a3d0793 to your computer and use it in GitHub Desktop.
Save wheelo/0e2d59fd303c6f4146477d675a3d0793 to your computer and use it in GitHub Desktop.
Custom Redux.useSelector() hook for React Native apps
import { useEffect, useReducer, useRef } from 'react';
import { useNavigation } from '@react-navigation/native';
import { useSelector } from 'react-redux';
const undefinedRef = Symbol();
const refEquality = (a: Object, b: Object) => a === b;
export function useAppSelector<Selected = unknown>(
selector: (state: RootState) => Selected,
ignoreUnfocusedScreens: boolean = true,
equalityFn?: (left: Selected, right: Selected) => boolean,
) {
const navigation = useNavigation();
const [, forceRender] = useReducer((s) => s + 1, 0);
const screenIsFocused = useRef(true);
const memoizedSelectorResult = useRef<Selected | Symbol>(undefinedRef);
const returnedSelectorResult = useRef<Selected | Symbol>(undefinedRef);
useEffect(() => {
const unsubscribeFocus = navigation.addListener('focus', () => {
screenIsFocused.current = true;
if (
memoizedSelectorResult.current !== undefinedRef &&
returnedSelectorResult.current !== undefinedRef
) {
const compareFn = equalityFn ?? refEquality;
const shouldForceRender = !compareFn(
memoizedSelectorResult.current as Selected,
returnedSelectorResult.current as Selected,
);
if (shouldForceRender) {
forceRender();
}
}
});
const unsubscribeBlur = navigation.addListener('blur', () => {
screenIsFocused.current = false;
});
return () => {
unsubscribeFocus();
unsubscribeBlur();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [navigation]);
return useSelector((state: RootState) => {
memoizedSelectorResult.current = selector(state);
if (
returnedSelectorResult.current === undefinedRef ||
screenIsFocused.current ||
!ignoreUnfocusedScreens
) {
returnedSelectorResult.current = memoizedSelectorResult.current;
}
return returnedSelectorResult.current as Selected;
}, equalityFn);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment