Reputation: 200
On the first <div>
, onDeleteClick
is working, but on the second one, the onDeleteClick
function is getting undefined
. I am getting the this
reference but click is not working, getting undefined
.
I am not able to understand why the first <div>
which has the function onDeleteClick
is working fine but for the second one that is a collection for which I am getting the reference of this
, but "onDeleteClick of undefined" is thrown on click of that.
onDeleteClick(e,data) {
e.preventDefault();
this.dataToBeDeleted = data;
this.setState({
showDeleteDialog: true
});
}
<PivotItem linkText="My Scenarios" itemCount={this.state.scenarios.length} >
<div className="tab-content">
<div className="details-table">
<table>
<thead>
<tr>
<th>Name</th>
<th>Last Modified</th>
<th>Owner</th>
<th className="actions">Actions</th>
</tr>
</thead>
<tbody>
{
this.state.scenarios.map((scenariosItem, sIndex) => {
return (
<tr className="list-row" key={sIndex}>
<td className="item-name">
<div>
<div className="item-icon"><i className="bod-industry-icon icon-Scenarios"></i></div>
<div className="item-info">{scenariosItem.title}
</div>
</div>
</td>
<td className="author">{moment(scenariosItem.utcDate).startOf('minutes').fromNow()}</td>
<td className="activity">{scenariosItem.creator}</td>
<td className="actions">
<IconButton iconProps={{ iconName: 'Edit' }}
title=""
ariaLabel="Edit"
onClick={
() => {
let url = '/c/scenarios/' + scenariosItem.ElementId;
window.open(url, '_self');
}
}
/>
<IconButton iconProps={{ iconName: 'EdgeLogo' }}
title=""
ariaLabel="Preview"
onClick={
() => {
let url = '/c/scenarios/' + scenariosItem.ElementId + "?preview=true";
window.open(url, '_blank');
}
}
/>
<IconButton iconProps={{ iconName: 'Delete' }}
title=""
ariaLabel="Delete"
onClick={
(e) => this.onDeleteClick(e, scenariosItem)
}
/>
</td>
</tr>
);
})
}
</tbody>
</table>
</div>
{
this.state.scenarios.length > 0 ? <a className="pull-right" href="/c/search/?type=8&cat=1">View all records</a> : null
}
</div>
</PivotItem>
<PivotItem linkText="My Collections" itemCount={this.state.collections.length} >
<div className="tab-content">
<div className="details-table">
<table>
<thead>
<tr>
<th>Name</th>
<th>Last Modified</th>
<th>Owner</th>
<th className="actions">Actions</th>
</tr>
</thead>
<tbody>
{
this.state.collections.map(function (collectionsItem, colIndex) {
const collectionIcon = collectionsItem.IndustryIcon ? collectionsItem.IndustryIcon : 'bod-industry-icon icon-Industry';
return (
<tr className="list-row" key={colIndex}>
<td className="item-name">
<div>
<div className="item-icon"><i className={collectionIcon}></i></div>
<div className="item-info">{collectionsItem.title}</div>
</div>
</td>
<td className="activity">{moment(collectionsItem.utcDate).startOf('minutes').fromNow()}</td>
<td className="author">{collectionsItem.creator}</td>
<td className="actions">
<IconButton iconProps={{ iconName: 'Edit' }}
title=""
ariaLabel="Edit"
onClick={
() => {
let url = '/c/collections/' + collectionsItem.ElementId;
window.open(url, '_self');
}
}
/>
<IconButton iconProps={{ iconName: 'EdgeLogo' }}
title=""
ariaLabel="Preview"
onClick={
() => {
let url = '/c/collections/' + collectionsItem.ElementId + "?preview=true";
window.open(url, '_blank');
}
}
/>
<IconButton iconProps={{ iconName: 'Delete' }}
title=""
ariaLabel="Delete"
onClick={
(e) => this.onDeleteClick(e, collectionsItem)
}
/>
</td>
</tr>
);
})
}
</tbody>
</table>
</div>
{
this.state.collections.length > 0 ? <a className="pull-right" href="/c/search/?type=26&cat=1">View all records</a> : null
}
</div>
</PivotItem>
Upvotes: 0
Views: 329
Reputation: 15290
Its related to lexical scope
issue.
Inside the anonymous function function (collectionsItem, colIndex) {
this
refer to global scope,which don't have definition for onDeleteClick
.
change this
this.state.collections.map(function (collectionsItem, colIndex) {
to
this.state.collections.map( (collectionsItem, colIndex)=> { //will bind class this
Upvotes: 2
Reputation: 86
Define your this.state.collections.map(function (collectionsItem, colIndex) {}) function as an arrow function.
Instead of defining it this way...
this.state.collections.map(function (collectionsItem, colIndex) {
})
Define it this way...
this.state.collections.map((collectionsItem, colIndex) => {
})
This will allow the function to inherit the arguments from its parent enclosing scope. In this case, it will inherit the arguments from the render function. Hence 'this' will reference the react component within your map function callback.
Also change your onDeleteClick definition to...
onDeleteClick = (e,data) => {
}
While working with React use arrow functions in most cases. However use normal functions while defining any of the react lifecycle functions such as componentDidMount, render, getDerivedStateFromProps etc.
componentDidMount() {
}
is correct.
Upvotes: 0
Reputation: 4333
The issue is with scoping.
Until arrow functions, every new function defined its own
this
value.
This means that, the this
inside this.state.collections.map(function(collectionsItem, colIndex){
is a different this
. You can use arrow functions, which will have the same this
in order for it to work. Use this.state.collections.map( (collectionsItem, colIndex) => {
for it to have the same this
.
Read more on arrow functions, and this
.
Upvotes: 0