UnstatedUtils.jsx 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. * create React component instance that is injected specified containers
  28. *
  29. * @param {object} componentClass wrapped React.Component class
  30. * @param {*} props
  31. * @param {*} containerClasses unstated container classes to subscribe
  32. * @returns returns such like a following element:
  33. * e.g.
  34. * <Subscribe to={containerClasses}> // containerClasses = [AppContainer, PageContainer]
  35. * { (appContainer, pageContainer) => (
  36. * <Component appContainer={appContainer} pageContainer={pageContainer} {...this.props} />
  37. * )}
  38. * </Subscribe>
  39. */
  40. export function createSubscribedElement(componentClass, props, containerClasses) {
  41. return (
  42. // wrap with <Subscribe></Subscribe>
  43. <Subscribe to={containerClasses}>
  44. { (...containers) => {
  45. const propsForContainers = generateAutoNamedProps(containers);
  46. return React.createElement(
  47. componentClass,
  48. Object.assign(propsForContainers, props),
  49. );
  50. }}
  51. </Subscribe>
  52. );
  53. }
  54. /**
  55. * Return a React component that is injected unstated containers
  56. *
  57. * @param {object} Component A React.Component or functional component
  58. * @param {array} containerClasses unstated container classes to subscribe
  59. * @returns returns such like a following element:
  60. * e.g.
  61. * <Subscribe to={containerClasses}> // containerClasses = [AppContainer, PageContainer]
  62. * { (appContainer, pageContainer) => (
  63. * <Component appContainer={appContainer} pageContainer={pageContainer} {...this.props} />
  64. * )}
  65. * </Subscribe>
  66. */
  67. export function withUnstatedContainers(Component, containerClasses) {
  68. return props => (
  69. // wrap with <Subscribe></Subscribe>
  70. <Subscribe to={containerClasses}>
  71. { (...containers) => {
  72. const propsForContainers = generateAutoNamedProps(containers);
  73. return <Component {...props} {...propsForContainers} />;
  74. }}
  75. </Subscribe>
  76. );
  77. }