UI_Dev
UI_Dev

Reputation: 200

Cannot read property 'onDeleteClick' of undefined

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

Answers (3)

RIYAJ KHAN
RIYAJ KHAN

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

Steve Sales
Steve Sales

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

illiteratewriter
illiteratewriter

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

Related Questions