LiamG_G LiamG_G - 1 month ago 7
Javascript Question

React: How to render same component with same onClick and different drops

I'm trying to use React Components to render all the projects I have in a .json. This is my code so far:

class App extends Component {
constructor(props){
super(props);
this.state = {
load: '',
projectInfo:{
"projects":[]
}
}
}

getProjectInfo(){
$.ajax({
url:'http://localhost:3000/projectInfo.json',
dataType:'json',
cache: false,
success: function(data){
this.setState({projectInfo: data});
}.bind(this),
error: function(xhr, status, err){
console.log(err);
alert(err);
}
});
}

componentDidMount(){
this.getProjectInfo();
}

handleClick = (value) => {
this.setState({load: value});
}

display(app){
if(app == 'bmi') {
return <Bmi />
}
if (app === 'js') {
return <Js />
}
else return "";
}

render() {
if(this.state.projectInfo){
var projects = this.state.projectInfo.projects.map(function(project){
return (<Project id={project.id}
projectName={project.name}
projectDescription={project.description}
imgAddress={project.imgAddress}
onClick={this.handleClick}/>)
})
}
return (
<div className="App">

<div className="App-header">

<h2>React Test</h2>

</div>
<div className="box">
{projects}

</div>
<div className={this.state.load}>
{this.display(this.state.load)}
</div>

</div>

);
}
}

export default App;


I'm having trouble with the onClick, getting the TypeError: Cannot read property 'handleClick' of undefined. I think the problem is that when I use {this.handleClick}, 'this' refers to 'project' passed to the function, but I'm not sure how to get around it.

This was working as desired when I manually listed all the Project Components to be rendered.

Answer Source

You did not bind the map for the context of this, but since you are using () => notation you can make use of the auto bind e.g.

  var projects = this.state.projectInfo.projects.map(project => {
      return (<Project id={project.id}
                     projectName={project.name}
                     projectDescription={project.description}
                     imgAddress={project.imgAddress}
                     onClick={this.handleClick}/>)
  })

EDIT:

To pass more arguments you have to use a callback for onClick e.g.

 onClick={() => this.handleClick(project.id)}