2017-01-22 2 views
0

Я строю меню боковой панели каркаса с помощью ReactJs и нужно понять, каким образом, чтобы вызвать функцию внутри ReactJsrender() функции.Реагировать, как правильно называть функциональный элемент внутри визуализации()

код ниже:

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 функции?

+0

пожалуйста, следующий формат времени кода перед отправкой! занимает ровно 2 секунды и делает его намного легче читать ... –

ответ

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; 
+0

Почему вы определили 'MenuItem' как функцию MenuItem ({key, ref, title, icon, submenu})', а не как другой компонент 'class MenuItem extends React.Component'? – Mendes

+0

Поскольку он не нуждается ни в каком состоянии, ни в любом из методов жизненного цикла компонента React. Поэтому я делаю это просто. – laruiss

+0

Не знал, что я могу определить его таким образом. Спасибо ... – Mendes

6

Указанный this, когда вы пытаетесь позвонить this.buildItem(), относится к контексту анонимной функции, а не к компоненту React.

При использовании Arrow Functions вместо функций, определенных с помощью ключевого слова function внутри метода render(), вы можете использовать this для ссылки на компонент и его методы React по желанию.

В качестве альтернативы вы можете использовать (function() { ... }).bind(this) для достижения того же результата. Но это более утомительно, и использование функций стрелок является предпочтительным.

+0

Где должна быть указана функция стрелки? Переместите 'buildItem' внутри' render() 'и определен как' buildItem => '? Пожалуйста, дополните. – Mendes

+0

Посмотрите код в моем ответе – laruiss

+0

@Mendes Вместо любой анонимной функции можно использовать функцию стрелки. Вы должны использовать функции стрелок вместо анонимных функций, находящихся в данный момент в вашем методе 'render(). Кроме того, если вы прочитаете ссылку на функции со стрелками, опубликованную выше, вы увидите, что функции стрелок всегда анонимны, поэтому попытка определить метод 'buildItem()' со стрелкой не будет работать. – fvgs

0

Вы можете добавить эту строку:

render() { 
    let that = this 
    return (

, а затем вместо this.buildItem использовать that.buildItem или вам может понадобиться that.buildItem.bind(that)

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