2015-03-02 2 views
0

Итак, я сейчас обновляю нашу версию React с .11.2 до .12.2. Я вижу много предупреждений о calling a React component directly. Use a factory or JSX instead.Обновление от React .11.2 до .12.2 прямое обращение к компоненту реакции

Вот один из моих реагировать классы, что претензии вызова среагировать компонент непосредственно:

function(
    Tab, //single tab (with content) 
    TabGroup, //group of tabs that can be collapsed, accordion-style 
    TabList //TabList module, independent of Tabpanel 
) { 
    /** 
    * What goes between the parent and child values when passed to Tabs 
    * @example 
    * <TabGroup val="p"> 
    *  <Tab val="c"></Tab> 
    * </TabGroup> 
    * //the child tab will have an actual value of 'p' + PARENT_CHILD_DELIMITER + 'c', or 'p__c' 
    * @const 
    * @type {String} 
    */ 
    var PARENT_CHILD_DELIMITER = '__'; 
    var SUBITEM_PREFIX = function() { 
     //TODO: Use <Icon> module 
     return '\u21B3 '; 
    }; 

    var oneTabItem = function(tab) { 
     return { 
      text: tab.props.text || tab.props.val, 
      val: tab.props.val, 
      data: { 
       type: 'tab' 
      } 
     }; 
    }; 

    /** 
    * Returns an array of config objects, to be passed along to Tabs module, 
    * generated off of a single TabGroup and its children. 
    * @param {TabGroup} tg The TabGroup in question 
    * @return {Object[]} 
    */ 
    var tabGroupItems = function(tg) { 
     /** 
     * The config for the collapsable group tab 
     * @type {Object} 
     */ 
     var groupItem = oneTabItem(tg); 

     //add the down arrow 
     //TODO: Use <Icon> module 
     // groupItem.text = [ 
     //  '\u25BC ', 
     //  groupItem.text 
     // ]; 

     groupItem.data.type = 'group'; 
     groupItem.data.state = 'open'; 

     //Build up an array of configs for all the relevant tabs for this TabGroup 
     return [groupItem].concat(_.values(React.Children.map(tg.props.children, function(child) { 
      var tabItem = oneTabItem(child); 
      tabItem.val = groupItem.val + PARENT_CHILD_DELIMITER + tabItem.val; 
      tabItem.text = [ 
       SUBITEM_PREFIX(), 
       tabItem.text 
      ]; 
      return tabItem; 
     }))); 
    }; 

    var tabsRef = 'tab-list'; 

    var Tabpanel = React.createClass({ 
     getInitialState: function() { 
      var tabGroupsChildren = this.tabGroupsChildren(), 
       selectedTabVal = this.props.initialSelected; 
      if (selectedTabVal in tabGroupsChildren) { 
       selectedTabVal = tabGroupsChildren[selectedTabVal][0]; 
      } 
      return { 
       selectedTabVal: selectedTabVal 
      }; 
     }, 
     getDefaultProps: function() { 
      return { 
       initialSelected: null 
      }; 
     }, 
     /** 
     * Returns a dictionary of each TabGroup's value to an array of its children's values. 
     * This is useful for deciding what should actually be selected after clicking on a 
     * parent tab (since TabGroups don't have any content of their own) 
     * @example 
     * Given: 
     * ```xml 
     * <TabGroup val="g1"> 
     *  <Tab val="a"></Tab> 
     *  <Tab val="b"></Tab> 
     * </TabGroup> 
     * <TabGroup val="g2"> 
     *  <Tab val="a"></Tab> 
     * </TabGroup> 
     * ``` 
     * Returns: 
     * ```javascript 
     * { 
     *  "g1": ["g1__a", "g1__b"], 
     *  "g2": ["g2__a"] 
     * } 
     * ``` 
     * @return {Object.<string, Array.<string>>} 
     */ 
     tabGroupsChildren: function() { 
      var self = this; 

      var set = {}; 

      React.Children.forEach(self.props.children, function(child) { 
       if (child instanceof TabGroup) { 
        //store array of children vals 
        set[child.props.val] = _.values(React.Children.map(child.props.children, 
         function(grandchild) { 
          return child.props.val + PARENT_CHILD_DELIMITER + grandchild.props.val; 
         } 
        )); 
       } 
      }); 

      return set; 
     }, 
     /** 
     * Returns a dictionary translating a tab's value to its content. 
     * Useful for determining which content should be shown. 
     * @return {Object} 
     */ 
     valToContent: function() { 
      var self = this; 

      var valToContent = {}; 

      React.Children.forEach(self.props.children, function(child) { 
       if (child instanceof Tab) { 
        valToContent[child.props.val] = child.props.children; 
       } else { 
        React.Children.forEach(child.props.children, function(grandchild) { 
         valToContent[child.props.val + PARENT_CHILD_DELIMITER + grandchild.props.val] = 
          grandchild.props.children; 
        }); 
       } 
      }); 

      return valToContent; 
     }, 
     /** 
     * Triggered when the selected tab is changed. 
     * Sets it to the first child if a TabGroup was selected. 
     * @param {string} newVal The val of the clicked tab 
     */ 
     tabChanged: function(newVal) { 
      var self = this; 

      var tabGroupsChildren = self.tabGroupsChildren(); 
      if (newVal in tabGroupsChildren && tabGroupsChildren[newVal].length) { 
       //when selecting a group, select the first item in that group 
       self.setState({selectedTabVal: tabGroupsChildren[newVal][0]}); 
       //make sure the state of the tabs module also gets updated 
       //(using string key so it doesn't get eaten by Closure) 
       self.refs[tabsRef].setState({val: tabGroupsChildren[newVal][0]}); 
      } else { 
       self.setState({selectedTabVal: newVal}); 
      } 
     }, 
     tabItems: function() { 
      var self = this; 
      var tabItem; 

      /* 
      * Lots of stuff going on here... 
      * 
      * First of all, flatten is converting a React object into a regular array 
      * (since the react object is typically {'.$1': Object, '.$2': Object}) 
      * 
      * From there, we're mapping each tab to the appropriately formatted 
      * dictionary that can be passed along to the Tabs module, 
      * using the above oneTabItem and tabGroupItems functions 
      * 
      * We only actually want all of the tabGroupItems if 
      * the TabGroup is active (expanded). Otherwise, we can just 
      * use a regular oneTabItem config, but with a closed arrow 
      */ 
      return _.flatten(_.values(React.Children.map(self.props.children, function(child) { 
       if (child instanceof Tab) { 
        return oneTabItem(child); 
       } else { 
        if (self.openGroup() === child.props.val) { 
         return tabGroupItems(child); 
        } else { 
         //closed TabGroup 
         //add the right arrow 
         //TODO: Use <Icon> module 
         tabItem = oneTabItem(child); 
         // tabItem.text = [ 
         //  '\u25B6 ', 
         //  tabItem.text 
         // ]; 
         tabItem.data.type = 'group'; 
         tabItem.data.state = 'closed'; 
         return tabItem; 
        } 
       } 
      }, self))); 
     }, 
     activeTabContent: function() { 
      return this.valToContent()[this.state.selectedTabVal] || <div></div>; 
     }, 
     openGroup: function() { 
      var delimiterIndex; 
      if (this.state.selectedTabVal == null) { 
       return ''; 
      } 
      delimiterIndex = this.state.selectedTabVal.indexOf(PARENT_CHILD_DELIMITER); 
      if (delimiterIndex === -1) { 
       return ''; 
      } else { 
       return this.state.selectedTabVal.substr(0, delimiterIndex); 
      } 
     }, 
     className: function() { 
      var self = this; 
      return 'tabpanel' + 
       (self.props.className ? ' ' + self.props.className : ''); 
     }, 
     render: function() { 
      var self = this; 

      return <div className={self.className()}> 
        <TabList 
         ref={tabsRef} 
         items={self.tabItems()} 
         initialSelected={self.state.selectedTabVal} 
         direction="column" 
         onChange={self.tabChanged} 
         tabClass="tabpanel-tab" /> 
        <div className="content"> 
         {self.activeTabContent()} 
        </div> 
       </div>; 
     } 
    }); 

    return Tabpanel; 

Я предполагаю, что этот вопрос находится в одном из следующих мест:

tabGroupsChildren: function() { 
    var self = this; 

    var set = {}; 

    React.Children.forEach(self.props.children, function(child) { 
     if (child instanceof TabGroup) { 
      //store array of children vals 
      set[child.props.val] = _.values(React.Children.map(child.props.children, 
       function(grandchild) { 
        return child.props.val + PARENT_CHILD_DELIMITER + grandchild.props.val; 
       } 
      )); 
     } 
    }); 

    return set; 
}, 
/** 
* Returns a dictionary translating a tab's value to its content. 
* Useful for determining which content should be shown. 
* @return {Object} 
*/ 
valToContent: function() { 
    var self = this; 

    var valToContent = {}; 

    React.Children.forEach(self.props.children, function(child) { 
     if (child instanceof Tab) { 
      valToContent[child.props.val] = child.props.children; 
     } else { 
      React.Children.forEach(child.props.children, function(grandchild) { 
       valToContent[child.props.val + PARENT_CHILD_DELIMITER + grandchild.props.val] = 
        grandchild.props.children; 
      }); 
     } 
    }); 

    return valToContent; 
} 

Или в рендер:

render: function() { 
    var self = this; 

    return <div className={self.className()}> 
      <TabList 
       ref={tabsRef} 
       items={self.tabItems()} 
       initialSelected={self.state.selectedTabVal} 
       direction="column" 
       onChange={self.tabChanged} 
       tabClass="tabpanel-tab" /> 
      <div className="content"> 
       {self.activeTabContent()} 
      </div> 
     </div>; 
} 

Любые идеи?

ответ

0

Основываясь на ответах на similar question, я думаю, что окончательное return Tabpanel; проблема (если предположить, что вызывающий код затем переходит на использование Tabpanel в качестве функции.)

Вместо этого, вы можете попробовать return React.createFactory(Tabpanel);

Смежные вопросы