in packages/recoil/hooks/Recoil_Hooks.js [425:485]
function useRecoilValueLoadable_TRANSITION_SUPPORT<T>(
recoilValue: RecoilValue<T>,
): Loadable<T> {
const storeRef = useStoreRef();
const componentName = useComponentName();
// Accessors to get the current state
const getLoadable = useCallback(() => {
if (__DEV__) {
recoilComponentGetRecoilValueCount_FOR_TESTING.current++;
}
const store = storeRef.current;
const storeState = store.getState();
const treeState = reactMode().early
? storeState.nextTree ?? storeState.currentTree
: storeState.currentTree;
return getRecoilValueAsLoadable(store, recoilValue, treeState);
}, [storeRef, recoilValue]);
const getState = useCallback(
() => ({loadable: getLoadable(), key: recoilValue.key}),
[getLoadable, recoilValue.key],
);
// Memoize state snapshots
const updateState = useCallback(
prevState => {
const nextState = getState();
return prevState.loadable.is(nextState.loadable) &&
prevState.key === nextState.key
? prevState
: nextState;
},
[getState],
);
// Subscribe to Recoil state changes
useEffect(() => {
const subscription = subscribeToRecoilValue(
storeRef.current,
recoilValue,
_state => {
setState(updateState);
},
componentName,
);
// Update state in case we are using a different key
setState(updateState);
return subscription.release;
}, [componentName, recoilValue, storeRef, updateState]);
// Get the current state
const [state, setState] = useState(getState);
// If we changed keys, then return the state for the new key.
// This is important in case the old key would cause the component to suspend.
// We don't have to set the new state here since the subscribing effect above
// will do that.
return state.key !== recoilValue.key ? getState().loadable : state.loadable;
}