Просмотр исходного кода

GC-1325: impl RevisionLoader

* lazy load with react-visibility-sensor
Yuki Takei 7 лет назад
Родитель
Сommit
224b1bef0b
3 измененных файлов с 51 добавлено и 4 удалено
  1. 1 0
      package.json
  2. 44 4
      src/client/js/components/Page/RevisionLoader.jsx
  3. 6 0
      yarn.lock

+ 1 - 0
package.json

@@ -193,6 +193,7 @@
     "react-dropzone": "^7.0.1",
     "react-frame-component": "^4.0.0",
     "react-i18next": "=7.13.0",
+    "react-visibility-sensor": "^5.0.2",
     "reveal.js": "^3.5.0",
     "sass-loader": "^7.1.0",
     "simple-load-script": "^1.0.2",

+ 44 - 4
src/client/js/components/Page/RevisionLoader.jsx

@@ -1,8 +1,13 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
+import VisibilitySensor from 'react-visibility-sensor';
+
 import RevisionRenderer from './RevisionRenderer';
 
+/**
+ * Load data from server and render RevisionBody component
+ */
 export default class RevisionLoader extends React.Component {
 
   constructor(props) {
@@ -11,17 +16,20 @@ export default class RevisionLoader extends React.Component {
 
     this.state = {
       markdown: '',
+      isLoading: false,
+      isLoaded: false,
       error: null,
     };
 
     this.loadData = this.loadData.bind(this);
-  }
-
-  componentWillMount() {
-    this.loadData();
+    this.onVisibilityChanged = this.onVisibilityChanged.bind(this);
   }
 
   loadData() {
+    if (!this.state.isLoaded && !this.state.isLoading) {
+      this.setState({ isLoading: true });
+    }
+
     const requestData = {
       page_id: this.props.pageId,
       revision_id: this.props.revisionId,
@@ -41,10 +49,42 @@ export default class RevisionLoader extends React.Component {
       })
       .catch(err => {
         this.setState({ error: err });
+      })
+      .finally(() => {
+        this.setState({ isLoaded: true, isLoading: false });
       });
   }
 
+  onVisibilityChanged(isVisible) {
+    this.logger.info(this.props.pagePath, isVisible);
+
+    if (!isVisible) {
+      return;
+    }
+
+    this.loadData();
+  }
+
   render() {
+    // ----- before load -----
+    if (!this.state.isLoaded) {
+      return <VisibilitySensor onChange={this.onVisibilityChanged} delayedCall={true}>
+        <div className="wiki"></div>
+      </VisibilitySensor>;
+    }
+
+    // ----- loading -----
+    if (!this.state.isLoaded) {
+      return (
+        <div className="wiki">
+          <div className="text-muted text-center">
+            <i className="fa fa-2x fa-spinner fa-pulse mr-1"></i>
+          </div>
+        </div>
+      );
+    }
+
+    // ----- after load -----
     let markdown = this.state.markdown;
     if (this.state.error != null) {
       markdown = `<span class="text-muted"><em>${this.state.error}</em></span>`;

+ 6 - 0
yarn.lock

@@ -7538,6 +7538,12 @@ react-transition-group@^2.0.0, react-transition-group@^2.2.0:
     prop-types "^15.5.8"
     warning "^3.0.0"
 
+react-visibility-sensor@^5.0.2:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/react-visibility-sensor/-/react-visibility-sensor-5.0.2.tgz#e360fff81572cb3a2a9fd680484447a9da09a55d"
+  dependencies:
+    prop-types "^15.6.2"
+
 react@^16.4.1:
   version "16.4.1"
   resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"