Как передать методы React обработчику onClick компонента html?

Я пытаюсь изменить HTML-код, полученный из базы данных, для ответа на пользовательские обработчики onClick. В частности, HTML-код, который я извлекаю, имеет div, называемые yui-navset, которые содержат селекторы страниц yui_nav и содержимое страницы yui_content. Я хочу щелкнуть li в yui_nav, установить для класса li значение «selected», установить для существующего содержимого display: none и установить для нового содержимого style = "".

Для этого я создал функцию updateTabs, которая вводит индекс выбранного yui и номер новой страницы, установил для этого класса li значение «selected», установил для существующего содержимого display: none и установил для нового содержимого style = "". Эта функция работает: я пробовал запустить updateTabs (2, 3) в componentDidUpdate, и он работал нормально, изменяя содержимое по запросу. Я хочу назначить updateTabs каждому из списков, и я пытаюсь сделать это в моем componentDidMount после моего запроса axios.

Однако я продолжаю получать ошибку: TypeError: this.updateTabs is not a function. Пожалуйста помоги?

Page.js:

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

class Page extends Component {
  constructor(props) {
    super(props);
    this.state = {
      innerHTML: "",
      pageTags: [],
    };
    console.info(this.props.url);
  }

  componentDidMount() {
    console.info(this.props.url);
    axios
      .get(
        this.props.db_address + "pages?url = " + this.props.url,
        {headers: {"Access-Control-Allow-Origin": "*"}}
      )
      .then(response => {
        this.setState({
          innerHTML: response.data[0].html,
          pageTags: response.data[1]
        });
        console.info(response);
        // Check for yui boxes, evade the null scenario
        var yui_sets = document.getElementsByClassName('yui-navset');
        if (yui_sets !== null) {
          let yui_set, yui_nav, yui_content;
          // Iterate through the navs of each set to find the active tabs
          for (var yui_set_count = 0; yui_set_count < yui_sets.length; yui_set_count ++) {
            yui_set = yui_sets[yui_set_count];
            yui_nav = yui_set.getElementsByClassName('yui-nav')[0].children;
            yui_content = yui_set.getElementsByClassName('yui-content')[0].children;
            let tab_count;
            // Give each nav and tab and appropriate ID for testing purposes
            for (tab_count = 0; tab_count < yui_nav.length; tab_count ++) {
              yui_nav[tab_count].onclick = function() { this.updateTabs(yui_set_count); }
              yui_nav[tab_count].id = "nav-"+ yui_set_count.toString() + "-" + tab_count.toString()
              yui_content[tab_count].id = "content-"+ yui_set_count.toString() + "-" + tab_count.toString()
            }
          }
        }
      })
      .catch(error => {
        this.setState({ innerHTML: "ERROR 404: Page not found." })
        console.info(error);
      });
  }

  updateTabs(yui_index, tab_index){
    // Get all yuis
    var yui_sets = document.getElementsByClassName('yui-navset');
    let yui_set, yui_nav, yui_content
    yui_set = yui_sets[yui_index];
    yui_nav = yui_set.getElementsByClassName('yui-nav')[0].children;
    yui_content = yui_set.getElementsByClassName('yui-content')[0].children;
    // Identify the current active tab
    var current_tab_found = false;
    var old_index = -1;
    while (current_tab_found == false) {
      old_index += 1;
      if (yui_nav[old_index].className === "selected") {
        current_tab_found = true;
      }
    }
    // Identify the new and old navs and contents
    var yui_nav_old = yui_nav[old_index]
    var yui_nav_new = yui_nav[tab_index]
    var yui_content_old = yui_content[old_index]
    var yui_content_new = yui_content[tab_index]
    // Give the new and old navs and contents their appropriate attributes
    yui_nav_old.className = "";
    yui_nav_new.className = "selected";
    yui_content_old.style = "display:none";
    yui_content_new.style = "";
  }

  render() {
    return (
      <div className = "Page">
        <div className = "Page-html col-12" dangerouslySetInnerHTML = {{__html:this.state.innerHTML}} />
        <div className = "Page-footer">
          <div className = "d-flex flex-wrap btn btn-secondary justify-content-around">
            {this.state.pageTags.map(function(pageTag){return(
              <div className = "pd-2" key = {pageTag.id}>
                {pageTag.name}
              </div>
            )})}
          </div>
          <div className = "d-flex justify-content-center" >
            <div className = "p-2">Discuss</div>
            <div className = "p-2">Rate</div>
            <div className = "p-2">Edit</div>
          </div>
          <div className = "d-flex justify-content-around App">
            <div className = "p-2">
              Unless otherwise stated, the content
              of this page is licensed under <br />
              <a href = "http://creativecommons.org/licenses/by-sa/3.0/"
              target = "_blank" rel = "noopener noreferrer">
                Creative Commons Attribution-ShareAlike 3.0 License
              </a>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default Page
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
65
2

Ответы 2

Вместо функции с ключевым словом function используйте стрелочные функции, и она будет решена следующим образом

У вас есть

yui_nav[tab_count].onclick = function() { this.updateTabs(yui_set_count); }

Но используйте

yui_nav[tab_count].onclick = () => { this.updateTabs(yui_set_count); }

Используйте это в методе componentDidMount

Хорошо, пусть он ссылается на функцию. Но теперь он всегда вызывает yui_set_count как глобальную переменную (которая заканчивается на 10 после каждого запуска), а не yui_set_count конкретной ссылки, по которой я нажимаю. Есть ли способ получить доступ к глобальному методу tihs.updateTabs и передать ему экземпляр this в качестве входного параметра?

Aidan Low 31.10.2018 02:42

Я предлагаю, если выше был ответ на вопрос, просто отметьте его сразу или отклоните и задайте новый вопрос. Или он смешает две вещи. Но все же отвечу на ваш следующий вопрос. заменить for (var yui_set_count = 0; на for (let yui_set_count = 0; т.е. заменить var на let

Aditya 31.10.2018 02:54
  1. Вы должны привязать метод updateTabs в конструкторе:

constructor(props) { super(props); ... this.updateTabs = this.updateTabs.bind(this); }

  1. Вы должны использовать стрелочные функции, чтобы вызвать этот метод с правильным контекстом:

yui_nav[tab_count].onclick = () => { this.updateTabs(yui_set_count); }

Другие вопросы по теме