useLegacyStore.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import {useEffect, useRef, useState} from 'react';
  2. import {Store} from 'reflux';
  3. import {SafeRefluxStore} from '../utils/makeSafeRefluxStore';
  4. import {CommonStoreDefinition} from './types';
  5. interface UnsafeStore extends Store, CommonStoreDefinition<any> {}
  6. interface SafeStore extends SafeRefluxStore, CommonStoreDefinition<any> {}
  7. type LegacyStoreShape = UnsafeStore | SafeStore;
  8. /**
  9. * This wrapper exists because we have many old-style enzyme tests that trigger
  10. * updates to stores without being wrapped in act.
  11. *
  12. * Wrting tests with React Testing Library typically circumvents the need for
  13. * this. See [0].
  14. *
  15. * [0]: https://javascript.plainenglish.io/you-probably-dont-need-act-in-your-react-tests-2a0bcd2ad65c
  16. */
  17. window._legacyStoreHookUpdate = update => update();
  18. /**
  19. * Returns the state of a reflux store. Automatically unsubscribes when destroyed
  20. *
  21. * ```
  22. * const teams = useLegacyStore(TeamStore);
  23. * ```
  24. */
  25. export function useLegacyStore<T extends LegacyStoreShape>(
  26. store: T
  27. ): ReturnType<T['getState']> {
  28. const [state, setState] = useState(store.getState());
  29. // Not all stores emit the new state, call get on change
  30. const callback = () => window._legacyStoreHookUpdate(() => setState(store.getState()));
  31. // If we setup the listener in useEffect, there is a small race condition
  32. // where the store may emit an event before we're listening (since useEffect
  33. // fires AFTER rendering). Avoid this by ensuring we start listening
  34. // *immediately* after we initialize the useState.
  35. const unlisten = useRef<Function>();
  36. if (unlisten.current === undefined) {
  37. unlisten.current = store.listen(callback, undefined);
  38. }
  39. useEffect(() => {
  40. return () => void unlisten.current?.();
  41. }, []);
  42. return state;
  43. }