How to avoid binding by using arrow functions in callbacks in ReactJS? How to bind ‘this’ keyword to resolve classical error message ‘state of undefined’ in React? Machine Learning and Data ScienceMachine Learning Basic and AdvancedComplete Data Science Program(Live)Data Analysis with Python Example 1: This example illustrates how to use arrow functions in callbacks
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", {
"decoratorsBeforeExport": false
}],
["@babel/plugin-transform-arrow-functions", {
"spec": true
}]
]
}
index.js:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<App />, document.querySelector('#root'))
App.js :
import React, { Component } from 'react'
class App extends Component {
// Default props
static defaultProps = {
courseContent : [
'JSX', 'React Props', 'React State', 'React Lifecycle Methods',
'React Event Handlers', 'React Router', 'React Hooks', 'Readux',
'React Context'
]
}
constructor(props){
super(props)
// Set initial state
this.state = {msg : 'React Course', content:''}
}
// Return an unordered list of contents
renderContent(){
return (
<ul>
{/* map over all the contents and
return some JSX for each */}
{this.props.courseContent.map(content => (
<li>{content}</li>
))}
</ul>
)
}
render(){
const button = !this.state.content &&
<button
// Arrow function in callback
onClick={() => {
// Update state
this.setState({
msg : 'Course Content',
content : this.renderContent()
})
}}
>
Click here to know contents!
</button>
return (
<div>
<p>{this.state.msg}</p>
<p>{this.state.content}</p>
{button}
</div>
)
}
}
export default App
Using Function.prototype.bind in render creates a new function each time the component renders, which may have performance implications (see below). Alternately, you can use DOM APIs to store data needed for event handlers. Consider this approach if you need to optimize a large number of elements or have a render tree that relies on React.PureComponent equality checks. There are several ways to make sure functions have access to component attributes like this.props and this.state, depending on which syntax and build steps you are using.
<button onClick={this.handleClick}>
class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>;
}
}
class Foo extends Component {
handleClick = () => {
console.log('Click happened');
};
render() {
return <button onClick={this.handleClick}>Click Me</button>;
}
}
class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={() => this.handleClick()}>Click Me</button>;
}
}
obj.method();
If you use arrow functions within render, each call to render will create new function objects. If you then pass these functions to child elements via props, optimizations based on PureComponent or shouldComponentUpdate will fail (as the arrow function props will change on every render). In an arrow function, this means the same thing within the function body as it does outside of it. Which means that if you use arrow functions within your component’s render or lifecycle methods, they can use this and this.setState with no surprises. Each time your browser executes a => statement, it needs to create a new function object. And this can be an expensive operation, depending on the circumstances.
import React from 'react'
import ReactDOM from 'react-dom'
class BrokenButton extends React.Component {
render() {
return (
<button onClick={this.handleClick} style={this.state}>
Set background to red
</button>
)
}
handleClick() {
this.setState({ backgroundColor: 'red' })
}
}
ReactDOM.render(
<BrokenButton />,
document.getElementById('root')
)
import React from 'react'
import ReactDOM from 'react-dom'
class Button extends React.Component {
render() {
return (
<button
onClick={() => this.setState({ backgroundColor: 'red' })}
style={this.state}
>
Set background to red
</button>
)
}
}
ReactDOM.render(
<Button />,
document.getElementById('root')
)
import React from 'react'
import ReactDOM from 'react-dom'
const a = (x) => x,
b = (x) => x
ReactDOM.render(
<div>
<h3>Are <code>a</code> and <code>b</code> equal by <code>==</code>?</h3>
<p>{a == b ? 'Yes!' : 'No :('}</p>
</div>,
document.getElementById('root')
)
import React from 'react'
import ReactDOM from 'react-dom'
class Button extends React.Component {
render() {
return (
<button onClick={this.handleClick} style={this.state}>
Set background to red
</button>
)
}
// Note: As of May 2020, this syntax is not yet part of
// JavaScript proper, but is slated for inclusion soon. It should
// already work with Babel or TypeScript
handleClick = () => {
this.setState({ backgroundColor: 'red' })
}
}
ReactDOM.render(
<Button />,
document.getElementById('root')
)
A bind call or arrow function in a JSX prop will create a brand new function on every single render. This is bad for performance, as it may cause unnecessary re-renders if a brand new function is passed as a prop to a component that uses reference equality check on the prop to determine if it should update. This will speed up rendering, as it avoids the need to create new functions (through bind calls) on every render. Note that this behavior is different for ref props, which is a special case in React that does not cause re-renders when a brand new function is passed. See ignore-refs below for more information.
<Foo onClick={this._handleClick.bind(this)}></Foo>
<Foo onClick={() => console.log('Hello!')}></Foo>
function onClick() { console.log('Hello!'); }
<Foo onClick={onClick} />
"react/jsx-no-bind": [<enabled>, {
"ignoreDOMComponents": <boolean> || false,
"ignoreRefs": <boolean> || false,
"allowArrowFunctions": <boolean> || false,
"allowFunctions": <boolean> || false,
"allowBind": <boolean> || false
}]
<div onClick={this._handleClick.bind(this) />
<span onClick={() => console.log("Hello!")} />
<button type="button" onClick={function() { alert("1337") }} />