React onClick handler in map function . Cannot read property 'handleButton' of undefined - reactjs

I want to send table's row info to my handleButton function but I got this error:
Cannot read property 'handleButton' of undefined
Is it possible to send row info to a function other than the 'map' function?
I have one table. I fill this with map function and I need one button here.
<Table data={this.state.data} striped bordered hover>
<thead>
<tr >
<th>RowID</th>
<th>Keyword</th>
<th>Language</th>
<th>Url</th>
<th>Rank</th>
<th>Like</th>
</tr>
</thead>
<tbody>
{this.state.keywords.map(function(e){
return (
<tr>
<td>{e.row_id}</td>
<td>{e.target_language_keyword}</td>
<td>{e.lang}</td>
<td>{e.url.toString().substring(0,40)} </td>
<td>{e.rank}</td>
<td><Button variant="success" onClick={() => {this.handleButton(this)}} size="lg"> Like</Button></td>
</tr>
)})}
</tbody>
</Table>
I have also handleButton function like this
handleButton = event =>{
alertify.success("Updated successfully")
}
and in construnctur
this.handleButton = this.handleButton.bind(this);

Use Arrow function instead of binding method with this keyword
const handleButton =(event)=>{
"Updated Successfully"
}
and called it using onClick={this.handleButton}

Related

What am I not understating about using Maps in React?

I am new to react however I have done this same(ish) thing multiple times, however, this time it is just not working - I am assuming there is something I am fundamentaily not understanding. Please help!
I have a good old table:
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<TableRowUser key={1} />
<TableRowUser key={2} />
<TableRowUser key={3} />
</tbody>
</table>
And a row:
import React from 'react';
const TableRowUser = () => {
return <tr>
<td>TEST</td>
<td>TEST</td>
</tr>;
};
export default TableRowUser;
This works just as expected.
However, when I change from hard code to using a map - nothing is rendered:
...
<tbody>
{users.map(user => {
console.log(user.name);
<TableRowUser key={user.id} />
})}
</tbody>
...
I should note - my data is fine as this console log prints correctly.
Just no TableRowUser is returned.
This appears trivial - What am I missing?
The issue you are running into is how arrow functions work.
You can do:
() => value
for a quick way to return a value, but if you are putting a body on the code, you need to use the return keyword
() => { return value }
Thus, your code should be:
<tbody>
{users.map(user => {
console.log(user.name);
return <TableRowUser key={user.id} />
})}
</tbody>
or just
<tbody>
{users.map(user => <TableRowUser key={user.id} />)}
</tbody>

Loop through array using Map in React throw error

I have a functional component which is reading data from an API. I have defined an Interface but unable to loop and display in table using Map in react.
error
index.js:1 Warning: Each child in a list should have a unique "key" prop.
Interface
export interface ISiteManager{
managerId: number,
name: string,
isDeleted: false
}
React functional component return template
...
return (
<div>
<h2>EziTracker Dashboard Report</h2>
{eziStatusCollection && eziStatusCollection.length >0 && (
<table className="table">
<thead>
<tr>
<th>ManagerId</th>
<th>Name</th>
<th>Is Deleted</th>
</tr>
</thead>
{
eziStatusCollection.map((item, index) => {
return(
<tbody>
<tr key={index}>
<td>{item.managerId}</td>
<td>{item.name}</td>
<td>{item.isDeleted}</td>
</tr>
</tbody>
)})
}
</table>)}
</div>
);
};
export default MyComponent;
Your table body should be outside the map, as it's looping it each time as well:
<tbody>
{
eziStatusCollection.map((item, index) => {
return(
<tr key={index}>
<td>{item.managerId}</td>
<td>{item.name}</td>
<td>{item.isDeleted}</td>
</tr>
)})
}
</tbody>
This way the map key will be associated with each child (tr) and the error shouldn't occur.

How do I access a table <td> via refs instead of id in React.js

How do I access a refs instead of an id defined in a td of a table? For example, in my React component, I have a td with id="myId". Please see code below:
`componentDidUpdate() {
if (document.getElementById('myId')) {
// I want to use refs instead of id here. How do I do that?
document.getElementById('myId').click();
}
}`
`return (
<div>
<table width="90%" height="90%">
<tbody>
<tr>
<td>{this.props.something}</td>
<td id="myId" onClick={() => this.props.someFunctionToRun()}>Click me
</td>
</tr>
</tbody>
</table>
</div>
);`
Simply use ref prop on td. Pass a internal argument as reference and assign to variable you want (i.e. this.nameInput)
To use it as DOM element, you must define it in constructor using .createRef() method.
Like :
constructor(props) {
super(props);
this.nameInput = React.createRef(); // define ref
}
componentDidUpdate() {
if (this.nameInput) {
// Use DOM element's native method here
this.nameInput.click();
}
}
return (
<div>
<table width="90%" height="90%">
<tbody>
<tr>
<td>{this.props.something}</td>
<td ref={input => {
this.nameInput = input;
}} onClick={() => this.props.someFunctionToRun()}>Click me
</td>
</tr>
</tbody>
</table>
</div>
);

Reactjs table row button click not working

Why in the following code Delete button click does not hit the delete method? What i am missing important thing? I am new to learn React.js
delete(e) {
console.log('Deleted');
}
static renderCatTable(Categories) {
return (
<table className='table table-striped'>
<thead>
<tr>
<th>Code</th>
<th></th>
</tr>
</thead>
<tbody>
{Categories.map(category =>
<tr key={category._id}>
<td>{category.code}</td>
<td><button onClick={this.delete} className="btn btn-danger">Delete</button></td>
</tr>
)}
</tbody>
</table>
);
}
I have defined the binding inside the constructor
this.delete = this.delete.bind(this);
The render function is given below.
render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: Category.renderCatTable(this.state.Categories);
return (
<div>
{contents}
</div>
);
}
Because that render method is static. By definition, static methods cannot access an instance variable. You should remove that modifier if possible and it should work.

How to get a onClick to work in a row - reactjs

I am trying to get a click even to work with a table in reactjs. My first attempt was to make the whole row clickable. Here is my code:
var UserList = React.createClass({
getInitialState: function() {
return getUsers();
},
handleClick: function(e) {
console.log("clicked");
},
render: function() {
var users = this.state.users.map(function(user) {
return (
<tr onClick={this.handleClick}>
<td>{user.name}</td>
<td>{user.age}</td>
<td></td>
</tr>
);
});
return(
<div className="container">
<table className="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Full Detail</th>
</tr>
</thead>
<tbody>
{users}
</tbody>
</table>
</div>
);
}
});
This did not work. I then tried to add a button in the table:
<button className="btn" onClick={this.handleClick}>Full Detail</button>
That also did not work. I have other onClick's working throughout my app, but how do I make this work with a table?
Your problem is the function of user that creates the table row is not bound to your react component. The value of this will not be your react component and handleClick will not exist as a property of this.
Try
var users = this.state.users.map(function(user) {
return (
<tr onClick={this.handleClick}>
<td>{user.name}</td>
<td>{user.age}</td>
<td></td>
</tr>
);}.bind(this);
});
Or use Underscore's bind if you want it to work on all browsers.
I'm new to react. How about this? You just wrap it in another function, then that function holds the closure scope and it calls it correctly.
No idea if this is bad practice or the performance difference, but it seems to work...
var users = this.state.users.map(function(user) {
return (
<tr onClick={()=>this.handleClick(user)}>
<td>{user.name}</td>
<td>{user.age}</td>
<td></td>
</tr>
);}.bind(this);
});
Binding creates a new object. Thus if you bind your function for N employees, you are inefficiently creating N new functions. A more elegant approach is to bind the function once, and pass a reference to every row. Your original code was quite close. This is what I would suggest:
handleClick = e => {
const user = this.state.users.find(u => u.uuid == e.target.dataset.uui)
console.log("clicked");
},
render() {
return(
<div className="container">
<table className="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Full Detail</th>
</tr>
</thead>
<tbody>
{this.state.users.map(user =>
(
<tr data-uuid={user.uuid} onClick={this.handleClick}>
<td>{user.name}</td>
<td>{user.age}</td>
<td>{user.details || ''}</td>
</tr>
)
)}
</tbody>
</table>
</div>
);
}
});

Resources