如何正确调用render()

时间:2017-01-22 15:36:46

标签: javascript reactjs

我正在使用 ReactJs 构建侧边栏菜单框架,并且需要了解在 ReactJs render()函数中调用函数的方法。

代码如下:

import React from 'react';

var menuData = require("./data/admin.menu.json");

class SidebarMenu extends React.Component {
  constructor(props) {
    super(props);
    this.state = { expanded: true };
    this.buildItem = this.buildItem.bind(this);
  };

  buildItem(title, ref, icon) {
    return (
      <div className={"item" + this.props.key}>
        <a href={ref}>{title}<i className={"fa " + icon} /></a>
      </div>
    );
  };

  render() {

    return (
      <div>
        {
          menuData.forEach(function (item) {
            this.buildItem(item.title, item.ref, item.icon);

            if (item.hasOwnProperty("submenu")) {
              item.submenu.forEach(function (subitem) {
                this.buildItem(subitem.title, subitem.ref, subitem.icon);
              });
            }
          })
        }

      </div>
    );
  };
}

export default SidebarMenu;

给定代码显示以下错误:

Uncaught TypeError: Cannot read property 'buildItem' of undefined

如何正确调用将在 ReactJs 函数中呈现数据的函数?

3 个答案:

答案 0 :(得分:6)

当您尝试呼叫 var numRows = 0; function addRow() { var newRow = document.createElement('tr'); newRow.innerHTML += "<td><select id='lot" + numRows + "' name='lot" + numRows + "' data-placeholder='Choose a Lot...' class='chosen-select' required><option value=''></option><option value='United States'>United States</option><option value='United States'>aawsd</option><option value='United States'>hhe</option><option value='United States'>Ugfdh</option><option value='United States'>ffy</option><option value='United States'>uhg</option></select></td><td><input name='timein" + numRows + "' type='time' required></td><td><input name='timeout" + numRows + "' type='time' required></td><td><input name='condition" + numRows + "' type='text' required></td><td><input name='plowed" + numRows + "' type='checkbox'></td><td><input name='shovelled" + numRows + "' type='checkbox'></td><td><input name='salted" + numRows + "' type='checkbox'><input name='saltamount" + numRows + "' type='number' style='width: 40px;' min=0></td><td><input name='people" + numRows + "' type='text' required></td>" var table = document.getElementById("entrytbody"); table.appendChild(newRow); $("#lot" + numRows).chosen(); numRows++; } addRow(); 时引用的this是指匿名函数的上下文,而不是您的React组件。

使用Arrow Functions代替使用this.buildItem()方法中function关键字定义的函数,您可以根据需要使用render()引用React组件及其方法。

或者,您可以使用this来获得相同的结果。但这更乏味,优选使用箭头功能。

答案 1 :(得分:2)

下面是一个解决方案,使用胖箭头,AKA箭头功能:

import React from 'react';

var menuData = require("./data/admin.menu.json");

class SidebarMenu extends React.Component {
    constructor(props) 
    {
        super(props);

        this.state = { expanded: true };

      this.buildItem = this.buildItem.bind(this);
  };

  buildItem(title, ref, icon) {

    return (
      <div className={"item" + this.props.key}>
        <a href={ref}>{title}<i className={"fa " + item.icon}/></a>
      </div>
    );
  };

  render() {

      return (
        <div>
          {
            menuData.forEach(item => {
              this.buildItem(item.title, item.ref, item.icon);

                if (item.hasOwnProperty("submenu"))
                {
                  item.submenu.forEach(subitem => {
                    this.buildItem(subitem.title, subitem.ref, subitem.icon);
                  });
                }

            })
          }

        </div>
      );
  };
}

export default SidebarMenu;

另一种解决方案是:

  render() {

      return (
        <div>
          {
            menuData.forEach(function (item) {
              this.buildItem(item.title, item.ref, item.icon);

                if (item.hasOwnProperty("submenu"))
                {
                  item.submenu.forEach(function (subitem) {
                    this.buildItem(subitem.title, subitem.ref, subitem.icon);
                  }.bind(this));
                }

            }.bind(this))
          }

        </div>
      );
  };
}

但是,IMO,最好的解决方案是使用组件重构代码:

import React, {PropTypes, Component} from 'react';

const menuData = require('./data/admin.menu.json');

function MenuItem({key, ref, title, icon, submenu}) {
  return (
    <div className={`item${key}`}>
      <a href={ref}>{title}<i className={`fa ${icon}`}/></a>
      if (submenu) {
        submenu.map((subitem) => <MenuItem {...subitem} />)
      }
    </div>
  );
}

MenuItem.propTypes = {
    key: PropTypes.string,
    title: PropTypes.string,
    ref: PropTypes.string,
    icon: PropTypes.string,
    submenu: PropTypes.array,
};

class SidebarMenu extends Component {
    constructor(props) {
        super(props);
        this.state = {
            expanded: true,
        };
    }

    render() {
        return (
            <div>
                {
                    menuData.map((subitem) => <MenuItem {...subitem} />)
                }
            </div>
        );
    }
}

export default SidebarMenu;

答案 2 :(得分:0)

您可以添加以下这一行:

render() {
    let that = this
    return (

然后代替this.buildItem使用that.buildItem,或者您可能需要that.buildItem.bind(that)