React.Js 0.14 - 不变违规:对象作为React子对象无效

时间:2015-10-23 18:50:34

标签: reactjs

  

我有2个子类和1个超类(3个组件):

     
      
  1. 导航(超级)
  2.   
  3. TopNavZone
  4.   
  5. MobileNavZone
  6.   
export default class Navigation extends Component {

  constructor(props) {
    super(props);
    this.state = {
      navItems: [],
      navMenu: []
   };
 }

 fetchNavItems(clientId) {
   NavMenuAPI.getAll(clientId)
     .then((response) => {
       const data = response.data;
       this.setState({ navItems: data });
       this.showNavMenu();
     });
   }
 }

每个子类调用componentDidMount中的fetch方法,然后获取数据后的fetch调用调用相应的子类的showMenu方法:

export default class TopNavZone extends Navigation {

  constructor(props) {
      super(props);
  }

  componentDidMount() {
    const clientId = this.props.clientId;
    // in super class
    this.fetchNavItems(clientId);
 }

 showNavMenu() {
   const navItems = this.state.navItems;
   const results = [];
   navItems.map((item, index) => {
    results.push(

     // whatever html markup belongs here for TopNavZone

   );
 });
   this.setState({ navMenu: results });
}

 render() {
   if (!this.state.navMenu) return <div>Loading</div>;
   return (
    <div>{ this.state.navMenu }</div>
   )
}

我知道错误消息告诉我的是什么。我知道React不再允许将对象渲染为子级。我试过......

React.addons.createFragment(results) 
在showNavMenu中

并收到无法创建未定义片段的错误。

我非常喜欢我的html远离渲染部分并重构到处理它的各个函数中,所以我真的不想用showNavMenu标记加载我的渲染部分。我只是假设在渲染部分的一行中调用它。

我该怎样做才能使这项工作变得干净整洁?

非常感谢!

1 个答案:

答案 0 :(得分:1)

我找到了解决方案,并使渲染部分保持整洁。

我解决方案的关键在于在渲染中执行映射而不是调用函数来执行相同的映射

所以.......

  1. 从超类'fetchNavItems中删除this.showNavMenu(),从状态中删除navMenu数组。

  2. 渲染现在看起来像这样:

    render() {
      if (!this.state.navItems) return <div>Loading ...</div>;
      return (
        <section>
          <nav>
            <ul>
               { this.state.navItems.map(this.showNavMenu.bind(this)) }
           </ul>
         </nav>
      </section>
     );
    }
    
  3. showNavMenu已更改为:

    showNavMenu(item) {
      const results = [];
      let subMenu = [];
      let childrenLength = 0;
      if (item.children !== undefined) {
        const children = item.children;
        childrenLength = children.length;
        subMenu = this.fetchSubMenu(children);
      }
      results.push(
        <li key={ item.index }>
            { item.title }
          </Link>
          { subMenu }
        </li>
      );
      return results;
    }
    
  4. fetchSubMenu:

     fetchSubMenu(children) {
      const results = [];
      children.map((child, idx) => {
        results.push(
          <div key={ idx }>
              <Link to={ child.linkTo }>
                { child.title }
              </Link>
          </div>
        );
      });
      return results;
    }