UnstatedUtils.jsx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /* eslint-disable import/prefer-default-export */
  2. import React from 'react';
  3. import { Subscribe } from 'unstated';
  4. /**
  5. * generate K/V object by specified instances
  6. *
  7. * @param {Array<object>} instances
  8. * @returns automatically named key and value
  9. * e.g.
  10. * {
  11. * appContainer: <AppContainer />,
  12. * exampleContainer: <ExampleContainer />,
  13. * }
  14. */
  15. function generateAutoNamedProps(instances) {
  16. const props = {};
  17. instances.forEach((instance) => {
  18. // get class name
  19. const className = instance.constructor.getClassName();
  20. // convert initial charactor to lower case
  21. const propName = `${className.charAt(0).toLowerCase()}${className.slice(1)}`;
  22. props[propName] = instance;
  23. });
  24. return props;
  25. }
  26. /**
  27. * Return a React component that is injected unstated containers
  28. *
  29. * @param {object} Component A React.Component or functional component
  30. * @param {array} containerClasses unstated container classes to subscribe
  31. * @returns returns such like a following element:
  32. * e.g.
  33. * <Subscribe to={containerClasses}> // containerClasses = [AppContainer, PageContainer]
  34. * { (appContainer, pageContainer) => (
  35. * <Component appContainer={appContainer} pageContainer={pageContainer} {...this.props} />
  36. * )}
  37. * </Subscribe>
  38. */
  39. export function withUnstatedContainers(Component, containerClasses) {
  40. return React.forwardRef((props, ref) => (
  41. // wrap with <Subscribe></Subscribe>
  42. <Subscribe to={containerClasses}>
  43. { (...containers) => {
  44. const propsForContainers = generateAutoNamedProps(containers);
  45. return <Component {...props} {...propsForContainers} ref={ref} />;
  46. }}
  47. </Subscribe>
  48. ));
  49. }