React + Map + Button doesn't work [duplicate] - javascript

This question already has answers here:
React 0.13 class method undefined
(2 answers)
Uncaught ReferenceError: handleClick is not defined - React
(3 answers)
Closed 5 years ago.
Basic functionality.
Print a list DONE
Adding a button to each list DONE
Button call a particular function. NOW WORKING!!!
THANKS ALL OF YOU GUYS! -
30/10/2017 - I found solution. In the end of const renderItems, I just added a simple this and works. of course, I forgot in this sample to add this.handleClick = this.handleClick.bind(this); on constructor. So now, is working to me
I already did research about it, and the best solution that I found was here: But every time that I try to use this guide: https://reactjs.org/docs/handling-events.html
But I always get the error:
Uncaught TypeError: Cannot read property 'handleClick' of undefined
and I can't understand why. What I did (or doing) wrong?
import React, { Component } from 'react';
import axios from 'axios';
class myApp extends Component {
constructor(props) {
super(props);
this.state = {
repos: []
};
this.handleClick = this.handleClick.bind(this); // ADDED
}
componentDidMount() {
var $this = this;
var URL = JSON;
axios.get(URL).then(function(res) {
$this.setState({
repos: res.data
});
})
.catch(function(e) {
console.log("ERROR ", e);
});
}
handleClick() {
console.log('this is:', this);
}
render() {
const renderItems = this.state.repos.map(function(repo, i) {
return <li
key={i}>
<a onClick={(e) => this.handleClick(e)} >Click here!</a>
<span className='repoName'>
{repo.full_name}
</span>
<hr />
</li>
}, this); // just added THIS!
return (
<ul>
{renderItems}
</ul>
<section className='target'>
Target
</section>
);
}
}
export default myApp;

Your this inside of (e) => this.handleClick(e) is not class this. Just do it this way onClick={this.handleClick}.This way you will have click event inside this in handleClick function. If you want class this inside handleClick, than do it this.handleClick.bind(this)

You get an undefined error because you have a missing parameter e in your method definition. handleClick() without a parameter has a different identity than handleClick(e).
Bind handleClick in your constructor: this.handleClick = this.handleClick.bind(this);
Then change the onClick prop to onClick={this.handleClick}. Never use arrow functions inside the render function, this creates new identities of the function on every re-render which is bad practice and might cause performance issues as your application grows.
You can also use the experimental public class fields syntax, then you can define your click handler like so;
handleClick = (e) => {
// Stuff
}
Like this, you don't need to do any binding and you can just put this.handleClick in your onClick prop.

Related

How to use props and state inside a function declaration in a class component? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
I have a class component which has a function inside it named printData() I want to make use of the states and props variable of the class inside this function. How can I do it?
Code -
class ReadData extends Component {
constructor(props) {
super(props);
this.state = {
data: ""
}
}
componentDidMount() {
this.setState({ data: "Hello World" })
}
printData(props) {
console.log(this.props.data)
}
render() {
return (
<div>
<p>{this.state.data}</p>
<button onClick={this.printData}>Print</button>
</div>
)
}
}
The actual code is different. This is an example of what I am trying to implement. The console says
Uncaught (in promise) TypeError: Cannot read property 'props' of undefined
Using this.state.data instead of this.props.data also did not work.
Note: The render return successfully prints the desired output on the
window. Also, I want to make use of Class component and not functional component
You need to either bind the function or use arrow functions () => {} for this to work.
See doc: https://reactjs.org/docs/handling-events.html
class ReadData extends Component {
constructor(props) {
super(props);
// This binding is necessary to make `this` work in the callback
this.printData = this.printData.bind(this);
}
printData() {
console.log(this.props.data)
}
render() {
return (
<div>
<p>{this.state.data}</p>
<button onClick={this.printData}>Print</button>
</div>
)
}
}
or
class ReadData extends Component {
// Use arrow function to make `this` work in the callback
printData = () => {
console.log(this.props.data)
}
render() {
return (
<div>
<p>{this.state.data}</p>
<button onClick={this.printData}>Print</button>
</div>
)
}
}

ReactJS bind method to class component

Im doing ReactJS course in Codeacademny and they confused me.
(EDIT - full code) Photo of the code :
and there's no constructor or anywhere call to any bind method for the scream class method.
However in further exercises they tell you can't do that.
I probably miss something.
Apparently this.scream is an arrow function. Arrow function does not require binding. It points to the right context by default.
scream = () => { ... }
and there's no constructor or anywhere call to any bind method for the scream class method.
You only have to bind this to the component instance when the method actually uses this internally.
That's not the case in your example, so there is no need to bind it. No matter how the method is executed, it will always produce the same output.
Here is an example without React to demonstrate the difference:
var obj = {
value: 42,
method1() { // doesn't use `this`
console.log("yey!");
},
method2() { // uses `this`
console.log(this.value);
},
};
obj.method1(); // works
obj.method2(); // works
var m1 = obj.method1;
var m2 = obj.method2;
m1(); // works
m2(); // BROKEN!
var m2bound = obj.method2.bind(obj);
m2bound(); // works
scream = () => { ... }
render() {
return <button onClick={()=>this.scream()}>AAAAAH!</button>;
}
ou have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as
onClick={this.handleClick}, you should bind that method.
When you define a component using an ES6 class, a common pattern is for an event handler to be a method on the class. For example, this Toggle component renders a button that lets the user toggle between “ON” and “OFF” states:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);```
You can simply use an arrow function (no need to bind in constructor).
scream = () => { console.log('Here') }
render() {
return <button onClick={this.scream}>AAAAAH!</button>;
}
Or you can call this function inline by.
render() {
return <button onClick={() => console.log('Here')}>AAAAAH!</button>;
}
You should use arrow functions for event handling to bind the function to the object. Other solution is to auto bind each function in the constructor like :
class Test{
constructor(){
Object.getOwnPropertyNames(Test.prototype).forEach(
method => this[method] = this[method].bind(this));
}
Read about #AutoBind decorator for more details.

Props value not showing on top of render to a function ReactJS

However the this.props.NotesAll retrieving object from another component and it's showing object's to under render() method but when I'm trying to use that this.props.NotesAll on top of render on a function to working with those object, and i'm trying to check the value with console on functions it's just always say's undefined shit. So please help me ReactNinja's what actually is the wrong is going on here.
Here codes you can have a look on them
export default class EditNotes extends Component {
constructor(props) {
super(props);
this.state ={};
}
handleEdit() {
console.log(this + ' Clicked on That ');
}
//Here it's throwing error when I'm trying to click and console. the problem is here. i want this.props.NotesAll value here also to finding elements from objects
handleDelete(id) {
let Notes = this.props.NotesAll;
console.log(Notes)
}
render() {
let noteItems;
//this.props.NotesAll working fine here.
if (this.props.NotesAll) {
noteItems = this.props.NotesAll.map( Note => {
return(
<li key={Note.id}>{Note.body}
<button onClick={this.handleEdit.bind(Note.id)} className="btn btn-primary btn-sm">Edit</button>
<button onClick={this.handleDelete.bind(Note.id)} className="btn btn-danger btn-sm">Delete</button></li>
);
});
}
return(
<div className="col-md-4">
<h3 className="header-ttile">Current Notes:</h3>
<ul className="note-item-wrapper">
{noteItems}
</ul>
</div>
);
}
}
You define the binding in a wrong way, first parameter will be the context to which you want to bind.
Use this:
<button onClick={this.handleDelete.bind(this, Note.id)}
Syntax:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg:
The value to be passed as the this parameter to the target function
when the bound function is called.
constructor(props) {
super(props);
this.state ={};
this.notes = props.notesAll;
this.handleDelete = this.handleDelete.bind(this);
}
And then try to access your this.notes inside your handeDelete function. I'm not sure because I'm not a react ninja neither, but I think it should work this way

Setting onClick of dynamic elements generated through document.createelement

I am trying to set onClick function of dynamic generated elements. The function has to set state.
var root = document.getElementById("results_container");
var title = document.createElement('a');
title.setAttribute("id", 'title');
title.onclick = function () {
this.setState({
isOpen: !this.state.isOpen
});
}.bind(this)
I am getting the Uncaught TypeError: Cannot read property 'state' of undefined and I am assuming that onclick function is unable to reach this.state. Please help
You can use jQuery function on. It binds the action even in newly generated element.
$(document).on('click', '#test', function() {
// statement here
})
For your reference: jQuery .on()
Your this variable is undefined... If you are using react, you need to store the reference to the component instance (this) somewhere, and pass that to your bind function. This is probably a very poor way to do this, however. If you are using react, you likely want something more like this:
class Results extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false
};
}
render() {
return <div>
<a onClick={()=>this.setState({isOpen:!this.state.isOpen})}>
Title
</a>
{this.state.isOpen ? this.getOpenContent() : null}
</div>;
}
getOpenContent() {
return <div> ... </div>;
}
}

Why is my onClick being called on render? - React.js

I have a component that I have created:
class Create extends Component {
constructor(props) {
super(props);
}
render() {
var playlistDOM = this.renderPlaylists(this.props.playlists);
return (
<div>
{playlistDOM}
</div>
)
}
activatePlaylist(playlistId) {
debugger;
}
renderPlaylists(playlists) {
return playlists.map(playlist => {
return <div key={playlist.playlist_id} onClick={this.activatePlaylist(playlist.playlist_id)}>{playlist.playlist_name}</div>
});
}
}
function mapStateToProps(state) {
return {
playlists: state.playlists
}
}
export default connect(mapStateToProps)(Create);
When I render this page, activatePlaylist is called for each playlist in my map. If I bind activatePlaylist like:
activatePlaylist.bind(this, playlist.playlist_id)
I can also use an anonymous function:
onClick={() => this.activatePlaylist(playlist.playlist_id)}
then it works as expected. Why does this happen?
You need pass to onClick reference to function, when you do like this activatePlaylist( .. ) you call function and pass to onClick value that returned from activatePlaylist. You can use one of these three options:
1. using .bind
activatePlaylist.bind(this, playlist.playlist_id)
2. using arrow function
onClick={ () => this.activatePlaylist(playlist.playlist_id) }
3. or return function from activatePlaylist
activatePlaylist(playlistId) {
return function () {
// you code
}
}
I know this post is a few years old already, but just to reference the latest React tutorial/documentation about this common mistake (I made it too) from https://reactjs.org/tutorial/tutorial.html:
Note
To save typing and avoid the confusing behavior of this, we will use
the arrow function syntax for event handlers here and further below:
class Square extends React.Component {
render() {
return (
<button className="square" onClick={() => alert('click')}>
{this.props.value}
</button>
);
}
}
Notice how with onClick={() => alert('click')}, we’re passing a
function as the onClick prop. React will only call this function after
a click. Forgetting () => and writing onClick={alert('click')} is a
common mistake, and would fire the alert every time the component
re-renders.
This behaviour was documented when React announced the release of class based components.
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html
Autobinding
React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.
Therefore we decided not to have this built-in into React's class model. You can still explicitly prebind methods in your constructor if you want.
import React from 'react';
import { Page ,Navbar, Popup} from 'framework7-react';
class AssignmentDashboard extends React.Component {
constructor(props) {
super(props);
this.state = {
}
onSelectList=(ProjectId)=>{
return(
console.log(ProjectId,"projectid")
)
}
render() {
return (
<li key={index} onClick={()=> this.onSelectList(item.ProjectId)}></li>
)}
The way you passing the method this.activatePlaylist(playlist.playlist_id), will call the method immediately. You should pass the reference of the method to the onClick event. Follow one of the below-mentioned implementation to resolve your problem.
1.
onClick={this.activatePlaylist.bind(this,playlist.playlist_id)}
Here bind property is used to create a reference of the this.activatePlaylist method by passing this context and argument playlist.playlist_id
2.
onClick={ (event) => { this.activatePlaylist.(playlist.playlist_id)}}
This will attach a function to the onClick event which will get triggered on user click action only. When this code exectues the this.activatePlaylist method will be called.

Categories

Resources