Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
105
rated 0 times [  107] [ 2]  / answers: 1 / hits: 21423  / 7 Years ago, wed, june 7, 2017, 12:00:00

I have the following ReactJS component:



articles_list.jsx



import React from 'react';
import marked from 'marked';
import './articles_list.css';

export default class ArticlesList extends React.Component {

constructor(props) {
super(props);
this.state = {
articles: null
}
}

componentWillMount() {
fetch('/articles_all')
.then(res => res.json())
.then(json => {
this.setState({
articles: json.articles
});
});
}

handleClick(e) {
e.preventDefault();
var elem = e.target;
var file = elem.getAttribute('data-file').split('.')[0];
fetch('/article/'+file, {
headers: {
'Accept': 'text/markdown'
}
})
.then(res => res.text())
.then(txt => marked(txt))
.then(html => document.getElementById('article-text').innerHTML = html)
}

render() {

var teste = []

if (this.state.articles === null) {
teste.push(<div id=no-articles key=1>No articles</div>)
} else {
{this.state.articles.forEach( function(element, index) {
teste.push(<div onClick={this.handleClick} data-file={element.file} className=articles-menu-item key={index.toString()}>{element.title}</div>);
}.bind(this))}
}

return(
<div className=articles-list>
<div className=articles-list-title>
ARTICLES
</div>
<div id=menu-body className=menu-body>{teste}</div>
</div>
);
}
}


As you may see, it fetches as list of articles and creates links. When these links are clicked the corresponding article is load in a certain area of the page.



The code is working perfectly, but now I need to load a certain article before any of the links to be clicked. Then I decided to break the code inside handleClick like this:



   loadArticle(file) {
fetch('/article/'+file, {
headers: {
'Accept': 'text/markdown'
}
})
.then(res => res.text())
.then(txt => marked(txt))
.then(html => document.getElementById('article-text').innerHTML = html)
}

handleClick(e) {
e.preventDefault();
var elem = e.target;
var file = elem.getAttribute('data-file').split('.')[0];
loadArticle(file);
}


My idea with this is to invoke loadArticle inside render to load an specific article when the component loads, like this:



return(
<div className=articles-list>
<div className=articles-list-title>
ARTICLES
</div>
<div id=menu-body className=menu-body>{teste}{this.loadArticle('my_specific_article')}</div>
</div>
);


It works and now my_specific_article loads correctly when I navigate to the page. But...



But now when I click the links, that were working fine before, I got an error




Uncaught ReferenceError: loadArticle is not defined




And if I do



   handleClick(e) {
e.preventDefault();
var elem = e.target;
var file = elem.getAttribute('data-file').split('.')[0];
this.loadArticle(file);
}


using this, then I get




Uncaught TypeError: Cannot read property 'loadArticle' of null




How should I deal with this? I know it is a matter of context but, being new to ReactJS, I really don't know how to proceed.



EDIT



This is not a duplicate of this question, as it was marked. The reason is simple. In the mentioned question the function to bind is a event handler and in my problem a function being called by another. In fact, my event handler (similar to the other question) was working fine without the bind, then we are not talking about the same thing.


More From » reactjs

 Answers
41

You must bind your custom functions in the constructor.
Modify your constructor like this.



constructor(props) {
super(props);
this.state = {
articles: null
}
this.handleClick = this.handleClick.bind(this);
this.loadArticle = this.loadArticle.bind(this);
}


Now everywhere you should call this function as this.handleClick & this.loadMore.



You can read about other binding patterns here. The one I've mentioned is number 4.



That is the preferred way in facebook docs as well.


[#57548] Friday, June 2, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
khalilb

Total Points: 173
Total Questions: 110
Total Answers: 105

Location: Honduras
Member since Thu, Mar 23, 2023
1 Year ago
;