withReactSubviews.js

From disqus.com, 8 Months ago, written in Plain Text, viewed 3 times.
URL https://pastebin.freepbx.org/view/966c5283 Embed
Download Paste or View Raw
  1. define('home/mixins/withReactSubviews',[
  2.     'underscore',
  3. ], function (
  4.     _
  5. ) {
  6.     'use strict';
  7.  
  8.     // Shared modules, only need to be required once
  9.     var React, ReactDOM;
  10.     var sharedModules = {};  // path to imported module
  11.  
  12.     /**
  13.      * Called once a module has been fetched. Saves the module
  14.      * for future uses, stores it in the component for future
  15.      * rendering, and calls any onFetch callbacks that have
  16.      * been saved on this component.
  17.      *
  18.      * @param  {function} module - The fetched module
  19.      * @param  {Object} component - The component for this view/module
  20.      */
  21.     var handleOnFetch = function (module, component) {
  22.         sharedModules[component.path] = module;
  23.         component.module = module;
  24.         component.fetching = false;
  25.  
  26.         _.each(component.onFetch, function (fn) {
  27.             if (fn)
  28.                 fn();
  29.         });
  30.     };
  31.  
  32.     /**
  33.      * Called once a component has been rendered into the DOM
  34.      * and we have a reference to it. Saves the ref for future
  35.      * component prop updates and calls on onRef callbacks that
  36.      * have been saved on this component.
  37.      *
  38.      * @param {ReactElement} ref - The ReactElement that has
  39.      *                               been rendered into the DOM
  40.      * @param  {Object} component - The component for this view/module
  41.      */
  42.     var handleRef = function (ref, component) {
  43.         component.ref = ref;
  44.  
  45.         _.each(component.onRef, function (fn) {
  46.             fn.call(component.ref);
  47.         });
  48.     };
  49.  
  50.     /**
  51.      * Lazy fetches react modules and react libraries. Tries to use
  52.      * previous imports if module has been imported before, and
  53.      * prevents multiple fetches from kicking off at once.
  54.      *
  55.      * @param  {Object}   component - The component whose module to fetch
  56.      * @param  {function} [callback] - A callback to call once the module
  57.      *                                 has been fetched/retrieved
  58.      */
  59.     var loadModule = function (component, callback) {
  60.         component.onFetch.push(callback);
  61.  
  62.         if (sharedModules[component.path]) {
  63.             handleOnFetch(sharedModules[component.path], component);
  64.             return;
  65.         }
  66.  
  67.         if (component.fetching)
  68.             return;
  69.  
  70.         component.fetching = true;
  71.  
  72.         // Require subview before react libraries because in production
  73.         // the libraries are bundled into the subview file and are not
  74.         // available to load until the subview file has been loaded.
  75.         require([
  76.             component.path,
  77.         ], function (Module) {
  78.             if (!React || !ReactDOM) {
  79.                 require([
  80.                     'react',
  81.                     'react-dom',
  82.                 ], function (
  83.                     iReact,
  84.                     iReactDOM
  85.                 ) {
  86.                     React = iReact;
  87.                     ReactDOM = iReactDOM;
  88.  
  89.                     handleOnFetch(Module, component);
  90.                 });
  91.             } else {
  92.                 handleOnFetch(Module, component);
  93.             }
  94.         });
  95.     };
  96.  
  97.     /**
  98.      * Mixin takes in a list of react modules that may be rendered by this view.
  99.      * Each module is specified by a path which will be used to reference it during
  100.      * render or updating the props for that subview.
  101.      *
  102.      * Rendering a react subview will automatically import the subview module
  103.      * and react libraries.
  104.      *
  105.      * @param  {string[]} modules - The list of module paths
  106.      */
  107.     var mixin = function (modules) {
  108.         this.initialize = _.wrap(this.initialize, function (_initialize) {
  109.             _initialize.apply(this, _.rest(arguments));
  110.  
  111.             // Since we map components by path, this view can only have 1
  112.             // instance of a component as a subview. Can change the mapping
  113.             // if need be.
  114.             this._components = _.chain(modules)
  115.                 .map(function (path) {
  116.                     return [path, {
  117.                         path: path,
  118.                         onFetch: [],
  119.                         onRef: [],
  120.                     }];
  121.                 })
  122.                 .object()
  123.                 .value();
  124.         });
  125.  
  126.         /**
  127.          * Renders the specified react component with the given props into
  128.          * the given element. Fetches the module and react libraries if
  129.          * necessary.
  130.          *
  131.          * @param  {string}   path - The path to fetch the module.
  132.          * @param  {Object}   props - The initial props to pass to the
  133.          *                            component.
  134.          * @param  {DOMElement}   el - The element into which to render
  135.          *                             the component.
  136.          * @param  {function} [callback] - A function that will be called
  137.          *                                 once the component exists in
  138.          *                                 the DOM.
  139.          */
  140.         this.renderReactSubview = function (path, props, el, callback) {
  141.             var component = this._components[path];
  142.             if (!component)
  143.                 return;
  144.  
  145.             if (!component.module) {
  146.                 loadModule(component, _.bind(this.renderReactSubview, this, path, props, el, callback));
  147.                 return;
  148.             }
  149.  
  150.             var ref = ReactDOM.render(
  151.                 React.createElement(React.createClass({
  152.                     displayName: 'wrapper',
  153.                     getInitialState: function () {
  154.                         return props;
  155.                     },
  156.                     render: function () {
  157.                         // Wrap component in an element with data-view-type=react. This is used to prevent
  158.                         // the global backbone anchor click handler from reloading when the clicks come
  159.                         // from a react page.
  160.                         return React.createElement('div', { 'data-view-type': 'react' },
  161.                             React.createElement(component.module, this.state)
  162.                         );
  163.                     },
  164.                 })),
  165.                 el,
  166.                 callback
  167.             );
  168.  
  169.             handleRef(ref, component);
  170.         };
  171.  
  172.         /**
  173.          * Updates the set of props given to the component specified by the
  174.          * given path. Expects the component to have been rendered via
  175.          * renderReactSubview previously, even if the module fetching/
  176.          * rendering is not yet complete.
  177.          *
  178.          * @param  {string} path - The path of the module which maps to a
  179.          *                         previously rendered component.
  180.          * @param  {Object} props - The new props to pass to the rendered
  181.          *                          component
  182.          */
  183.         this.updateComponentProps = function (path, props) {
  184.             var component = this._components[path];
  185.             if (!component)
  186.                 return;
  187.  
  188.             if (!component.ref) {
  189.                 component.onRef.push(function () {
  190.                     component.ref.setState(props);
  191.                 });
  192.                 return;
  193.             }
  194.  
  195.             component.ref.setState(props);
  196.         };
  197.     };
  198.  
  199.     // Used only for testing
  200.     mixin.forget = function () {
  201.         sharedModules = {};
  202.         React = undefined;
  203.         ReactDOM = undefined;
  204.     };
  205.  
  206.     return mixin;
  207. });
  208.  
  209. // https://c.disquscdn.com/next/82c6de3/home/js/mixins/withReactSubviews.js

Replies to withReactSubviews.js rss

Title Name Language When
Re: withReactSubviews.js disqus.com javascript 8 Months ago.
Re: withReactSubviews.js disqus.com javascript 8 Months ago.

Reply to "withReactSubviews.js"

Here you can reply to the paste above