Создание якоря с помощью onClick, который обрабатывает React

У меня есть компонент React, который отображает <ul> и вставляет элементы <li> в зависимости от состояния.

class SimpleComponent extends React.Component {
  constructor(props) {
    this.state = { menu_items: [name: "First", id: 10] }
    this.clickMenu = this.clickMenu.bind(this)
  }
  generateLinks() {
    let to_return='';
    for (var i=0;i<this.state.menu_items.length; i++) {
      to_return = to_return + `<li><a onclick={clickMenu}> ${this.state.menu_item[i]['name']} </a></li>`
     }
     return to_return;
   }
   clickMenu(e) {
     console.log(e.target)
   }
   render() {
     return(
       <ul dangerouslySetInnerHTML={this.generateLinks()}></ul>
     )
   }
}

Когда я нажимаю на якорь, консоль показывает Uncaught ReferenceError: clickMenu не определено. Вместо этого я пытался использовать this.clickMenu, но ничего не происходит. Я заметил, что визуализированный якорь выглядит так:

<a onclick="{menuClick}">

Есть ли способ создать эти элементы привязки, чтобы React подбирал определения onClick, а не передавал их в браузер для интерпретации?


person Andy Gauge    schedule 20.12.2017    source источник
comment
Почему бы не взять clickMenu из generateLinks и не сделать его собственным элементом-прототипом? Тогда вы можете просто использовать его как this.clickMenu   -  person Andrew    schedule 20.12.2017
comment
Я пытаюсь создать achor, который вызывает this.clickMenu при нажатии. clickMenu Я считаю, что это означает, что это элемент-прототип. Я не могу понять, что такое прототип элемента.   -  person Andy Gauge    schedule 20.12.2017
comment
Извините за путаную формулировку. Я хотел быть максимально техническим. Когда я говорю элемент прототипа, я имею в виду метод класса. В JavaScript нет настоящих классов, поэтому называть его таковым в корне неверно.   -  person Andrew    schedule 20.12.2017


Ответы (1)


С React вы должны создавать компоненты и подкомпоненты, а не составлять длинные строки HTML. Вы в основном подрываете шаблон использования React, и именно поэтому атрибут, который вы используете, содержит слово «опасно».

Вот один из способов реализации этого списка:

class SimpleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { menu_items: [{ name: "First", id: 10 }] };
    this.clickMenu = this.clickMenu.bind(this);
  }
  clickMenu(id) {
    console.log(id);
  }
  render() {
    var items = this.state.menu_items.map(item => {
      let handleClick = () => {
        this.clickMenu(item.id);
      };
      return (
        <li key={item.id}>
          <a onClick={handleClick}>
            {item.name}
          </a>
        </li>
      );
    });
    return <ul>{items}</ul>;
  }
}

Я создаю массив из <li> элементов, сопоставляя state.menu_items. Поскольку компонент повторно отображается при изменении состояния, он всегда будет обновляться в соответствии с текущим state (и вносить только те изменения, которые действительно необходимы, что является одной из определяющих характеристик React).

Также обратите внимание, что в вашем конструкторе отсутствует вызов super(props), а единственный элемент вашего массива состояний не заключен в фигурные скобки.

person Chris G    schedule 20.12.2017
comment
Возможно, вы захотите использовать стрелочные функции в объявлениях методов ваших компонентов, что позволит вам избавиться от необходимости связывать this для этих методов. например: clickMenu = (id) => {, и удалите строку, которая идет this.clickMenu = this.clickMenu.bind(this);. Живой пример здесь. Лучшее объяснение, которое я нашел на данный момент, это в документации по TypeScript, но это применимо к классам ES6 в целом, а не только к TypeScript (см. абзац «Использование функций экземпляра» в разделе «Исправления»). - person aurelienshz; 20.12.2017
comment
@aurelienshz Верно, но мой ответ в первую очередь касается реализации списка, а не контекста, на который ссылается this. Я не хотел превращать его в учебник по React;) - person Chris G; 20.12.2017
comment
Хорошо, это сработало. Я ценю усилия. Не думал о сборке ответа в методе рендеринга. Современный JavaScript становится все более сложным. @aurelienshz сегодня утром я узнал о цепочке связывания (этой). Крис Г: Я вижу опечатки, этот код был экстраполирован из фактического кода, чтобы проиллюстрировать конкретную проблему, с которой я столкнулся. - person Andy Gauge; 20.12.2017
comment
Ваше увещевание не создавать шаткие HTML-строки было суровым, но очень полезным для меня. Можно сойти с пути ReactJS и попасть в кроличью нору странных шаблонов обработки кликов. Но лучше оставаться на дороге более пройденной. В итоге я поместил свою ссылку в совершенно отдельный компонент React. - person John Gorenfeld; 17.06.2021