ayanami
Version:
A better way to react with state
42 lines (41 loc) • 1.58 kB
JavaScript
import * as React from 'react';
import identity from 'lodash/identity';
import shallowEqual from 'shallowequal';
export function useSubscribeAyanamiState(ayanami, selector = identity) {
const [state, setState] = React.useState(() => selector(ayanami.getState()));
const ayanamiRef = React.useRef(null);
const subscriptionRef = React.useRef(null);
const stateRef = React.useRef(state);
const isFirstRenderRef = React.useRef(true);
if (ayanamiRef.current !== ayanami) {
ayanamiRef.current = ayanami;
if (subscriptionRef.current) {
subscriptionRef.current.unsubscribe();
subscriptionRef.current = null;
}
if (ayanami) {
subscriptionRef.current = ayanami.getState$().subscribe((moduleState) => {
if (isFirstRenderRef.current)
return;
if (selector === identity) {
setState(selector(moduleState));
stateRef.current = selector(moduleState);
}
else {
const before = stateRef.current;
const after = selector(moduleState);
if (!shallowEqual(before, after))
setState(after);
stateRef.current = after;
}
});
}
}
React.useEffect(() => () => {
if (subscriptionRef.current) {
subscriptionRef.current.unsubscribe();
}
}, [subscriptionRef]);
isFirstRenderRef.current = false;
return state;
}