hook.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. import { useState, useEffect } from 'react';
  2. import { env } from './env';
  3. const cache = new WeakMap();
  4. const NO_OPTIONS = {};
  5. export function useSidecar(importer, effect) {
  6. const options = (effect && effect.options) || NO_OPTIONS;
  7. if (env.isNode && !options.ssr) {
  8. return [null, null];
  9. }
  10. // eslint-disable-next-line react-hooks/rules-of-hooks
  11. return useRealSidecar(importer, effect);
  12. }
  13. function useRealSidecar(importer, effect) {
  14. const options = (effect && effect.options) || NO_OPTIONS;
  15. const couldUseCache = env.forceCache || (env.isNode && !!options.ssr) || !options.async;
  16. const [Car, setCar] = useState(couldUseCache ? () => cache.get(importer) : undefined);
  17. const [error, setError] = useState(null);
  18. useEffect(() => {
  19. if (!Car) {
  20. importer().then((car) => {
  21. const resolved = effect ? effect.read() : car.default || car;
  22. if (!resolved) {
  23. console.error('Sidecar error: with importer', importer);
  24. let error;
  25. if (effect) {
  26. console.error('Sidecar error: with medium', effect);
  27. error = new Error('Sidecar medium was not found');
  28. }
  29. else {
  30. error = new Error('Sidecar was not found in exports');
  31. }
  32. setError(() => error);
  33. throw error;
  34. }
  35. cache.set(importer, resolved);
  36. setCar(() => resolved);
  37. }, (e) => setError(() => e));
  38. }
  39. }, []);
  40. return [Car, error];
  41. }