React中map内普通函数报错、箭头函数正常的原因咨询
this.onDeleteHandler Throws an Error in map with a Regular Function (and How Arrow Functions Fix It) Hey there! Let's break down exactly what's going on here—this all boils down to how JavaScript handles this binding, a super common gotcha in React class components.
First: Why the regular map function caused the error
When you pass a regular function as the callback to map, like this:
// The problematic code this.props.objList.map(function(row) { return <TableRow onDelete={this.onDeleteHandler} />; });
The this inside that regular function doesn't point to your component instance. By default, regular functions have their this determined by how they're called. In strict mode (which React uses), when map invokes the callback, this is undefined—hence the error: "Cannot read property 'onDeleteHandler' of undefined".
Your onDeleteHandler is defined as a class property arrow function:
onDeleteHandler = () => { axios.delete(`my_firebase_link${this.props.obj.id}.json`) .then(() => console.log('Deleted')) .catch(err => console.log(err)); };
This arrow function has lexical this binding—meaning it captures the this value from the surrounding scope (your component instance) when it's defined. But if the map callback can't access the component's this, it can't reach onDeleteHandler either.
How the arrow function map fixes it
When you switch to an arrow function for the map callback:
// The working code this.props.objList.map(row => { return <TableRow onDelete={() => this.onDeleteHandler(row.id)} />; });
Arrow functions don't have their own this—they inherit it from the outer scope (in this case, the render method, where this points to your component instance). That means this.onDeleteHandler correctly references the class property method you defined.
The nested arrow function for onDelete serves two purposes:
- It lets you pass the
row.idparameter toonDeleteHandler(since directly passingthis.onDeleteHandler(row.id)would invoke the method immediately, not when the delete button is clicked). - It preserves the
thisbinding ofonDeleteHandler—since the nested arrow function inheritsthisfrom themaparrow function, which in turn inherits it from the component.
Quick fixes for the regular function approach (if you ever want to use it)
If you prefer using a regular function with map, you have two options to fix the this issue:
- Bind
thisto the callback:this.props.objList.map(function(row) { return <TableRow onDelete={this.onDeleteHandler} />; }.bind(this)); - Capture
thisin a variable:const that = this; this.props.objList.map(function(row) { return <TableRow onDelete={that.onDeleteHandler} />; });
Key takeaway
- Regular functions have dynamic
thisbinding (depends on how they're called). - Arrow functions have lexical
thisbinding (inherits from the outer scope). - Class property arrow functions lock in
thisto the component instance, so you just need to ensure the surrounding scope can access that instance'sthis.
内容的提问来源于stack exchange,提问作者Lorenzo

