Я пытаюсь изменить 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



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вместо функции с ключевым словом function используйте стрелочные функции, и она будет решена следующим образом
У вас есть
yui_nav[tab_count].onclick = function() { this.updateTabs(yui_set_count); }
Но используйте
yui_nav[tab_count].onclick = () => { this.updateTabs(yui_set_count); }
Используйте это в методе componentDidMount
Я предлагаю, если выше был ответ на вопрос, просто отметьте его сразу или отклоните и задайте новый вопрос. Или он смешает две вещи. Но все же отвечу на ваш следующий вопрос. заменить for (var yui_set_count = 0; на for (let yui_set_count = 0; т.е. заменить var на let
updateTabs в конструкторе:
constructor(props) {
super(props);
...
this.updateTabs = this.updateTabs.bind(this);
}
yui_nav[tab_count].onclick = () => { this.updateTabs(yui_set_count); }
Хорошо, пусть он ссылается на функцию. Но теперь он всегда вызывает yui_set_count как глобальную переменную (которая заканчивается на 10 после каждого запуска), а не yui_set_count конкретной ссылки, по которой я нажимаю. Есть ли способ получить доступ к глобальному методу tihs.updateTabs и передать ему экземпляр this в качестве входного параметра?