Yuki Takei 6 лет назад
Родитель
Сommit
b233ec8a91
2 измененных файлов с 66 добавлено и 24 удалено
  1. 5 24
      src/client/js/components/PageComments.jsx
  2. 61 0
      src/client/js/components/UnstatedUtils.jsx

+ 5 - 24
src/client/js/components/PageComments.jsx

@@ -2,9 +2,8 @@
 /* eslint-disable react/no-access-state-in-setstate */
 import React from 'react';
 import PropTypes from 'prop-types';
-import Button from 'react-bootstrap/es/Button';
 
-import { Subscribe } from 'unstated';
+import Button from 'react-bootstrap/es/Button';
 
 import { withTranslation } from 'react-i18next';
 import GrowiRenderer from '../util/GrowiRenderer';
@@ -12,6 +11,7 @@ import GrowiRenderer from '../util/GrowiRenderer';
 import AppContainer from '../services/AppContainer';
 import CommentContainer from '../services/CommentContainer';
 
+import { createSubscribedElement } from './UnstatedUtils';
 import CommentEditor from './PageComment/CommentEditor';
 
 import Comment from './PageComment/Comment';
@@ -237,23 +237,9 @@ class PageComments extends React.Component {
 
 }
 
-/**
- * Wrapper component for using unstated
- */
-class PageCommentsWrapper extends React.Component {
-
-  render() {
-    return (
-      <Subscribe to={[AppContainer, PageContainer, CommentContainer]}>
-        { (appContainer, pageContainer, commentContainer) => (
-          // eslint-disable-next-line arrow-body-style
-          <PageComments appContainer={appContainer} pageContainer={pageContainer} commentContainer={commentContainer} {...this.props} />
-        )}
-      </Subscribe>
-    );
-  }
-
-}
+const PageCommentsWrapper = (props) => {
+  return createSubscribedElement(PageComments, props, [AppContainer, PageContainer, CommentContainer]);
+};
 
 PageComments.propTypes = {
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
@@ -264,10 +250,5 @@ PageComments.propTypes = {
   revisionCreatedAt: PropTypes.number,
   slackChannels: PropTypes.string,
 };
-PageCommentsWrapper.propTypes = {
-  crowiOriginRenderer: PropTypes.object.isRequired,
-  revisionCreatedAt: PropTypes.number,
-  slackChannels: PropTypes.string,
-};
 
 export default withTranslation(null, { withRef: true })(PageCommentsWrapper);

+ 61 - 0
src/client/js/components/UnstatedUtils.jsx

@@ -0,0 +1,61 @@
+/* eslint-disable import/prefer-default-export */
+
+import React from 'react';
+import { Subscribe } from 'unstated';
+
+/**
+ * generate K/V object by specified instances
+ *
+ * @param {Array<object>} instances
+ * @returns automatically named key and value
+ *   e.g.
+ *   {
+ *     appContainer: <AppContainer />,
+ *     exampleContainer: <ExampleContainer />,
+ *   }
+ */
+function generateAutoNamedProps(instances) {
+  const props = {};
+
+  instances.forEach((instance) => {
+    // get class name
+    const className = instance.constructor.name;
+    // convert initial charactor to lower case
+    const propName = `${className.charAt(0).toLowerCase()}${className.slice(1)}`;
+
+    props[propName] = instance;
+  });
+
+  return props;
+}
+
+/**
+ * create React component instance that is injected specified containers
+ *
+ * @param {object} componentClass wrapped React.Component class
+ * @param {*} props
+ * @param {*} containerClasses unstated container classes to subscribe
+ * @returns returns such like a following element:
+ *  e.g.
+ *  <Subscribe to={containerClasses}>  // containerClasses = [AppContainer, PageContainer]
+ *    { (appContainer, pageContainer) => (
+ *      <Component appContainer={appContainer} pageContainer={pageContainer} {...this.props} />
+ *    )}
+ *  </Subscribe>
+ */
+export function createSubscribedElement(componentClass, props, containerClasses) {
+  return (
+    // wrap with <Subscribe></Subscribe>
+    <Subscribe to={containerClasses}>
+      { (...containers) => {
+        const propsForContainers = generateAutoNamedProps(containers);
+
+        return React.createElement(
+          componentClass,
+          Object.assign(propsForContainers, props),
+        );
+      }}
+    </Subscribe>
+  );
+
+}