Why Shouldn't Jsx Props Use Arrow Functions or Bind

Why shouldn't JSX props use arrow functions or bind?

Why you shouldn't use inline arrow functions in JSX props

Using arrow functions or binding in JSX is a bad practice that hurts performance, because the function is recreated on each render.

  1. Whenever a function is created, the previous function is garbage collected. Rerendering many elements might create jank in animations.

  2. Using an inline arrow function will cause PureComponents, and components that use shallowCompare in the shouldComponentUpdate method to rerender anyway. Since the arrow function prop is recreated each time, the shallow compare will identify it as a change to a prop, and the component will rerender.

As you can see in the following 2 examples - when we use inline arrow function, the <Button> component is rerendered each time (the console shows the 'render button' text).

Example 1 - PureComponent without inline handler

class Button extends React.PureComponent {  render() {    const { onClick } = this.props;        console.log('render button');        return (      <button onClick={ onClick }>Click</button>    );  }}
class Parent extends React.Component { state = { counter: 0 } onClick = () => this.setState((prevState) => ({ counter: prevState.counter + 1 })); render() { const { counter } = this.state; return ( <div> <Button onClick={ this.onClick } /> <div>{ counter }</div> </div> ); }}
ReactDOM.render( <Parent />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script><script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script><div id="root"></div>

JSX props should not use arrow functions eslint warning

The problem with your code is that you're passing a callback as a property directly. You could declare it as a wrapper using useCallback before passing it down to the component, like so:

const doSmthHandlerWrapper = useCallback(
() => doSmthHandler(id),
[id]
)

<ComponentB>
doSmth={doSmthHandlerWrapper}
</ComponentB>

setState and JSX props should not use arrow functions

You can set id or name of an element same with the name of a state variable. So you can create one function and pass it to all inputs like:

onFieldChange = (e) => {
const key = e.target.id
const value = e.target.value
this.setState({[key]:value})
}

Bind vs Arrow Function when passing onChange props (React)

Since it is only using a reference to the function, we are not causing a re-render each time

You're wrong.

The bind method returns a new function (so will trigger a re-render).


To avoid re-renders, make use of the useCallback hook.

Or, since you don't appear to be making use of this inside myFunction (otherwise () => myFunction() would break it), just pass myFunction itself without creating a new function.

onClick={myFunction}

No .bind() or Arrow Functions in JSX Props making no sense to me when I need to pass arguments

Either using bind and arrow functions, will create a new function passing a completely new prop to your component, causing unnecessary rerenders and extra work for the garbage collector, using data-attributes is a bad design and is not the React way of doing things, you should not access the DOM directly, but rather let React handle things. Instead of that you can just make a new component and pass the the handler as a prop, handling the "binding" of the id in a method of the component:

class User extends Component {
handleClick() {
this.props.handleToggleActive(this.props.user.id);
}

render() {
return (
<li>
<Link to={`/users/${this.props.user.id}`}>{this.props.user.name}</Link>
<Button onClick={this.handleClick}>Toggle Active</Button>
</li>
)
}
}

export class UserList extends Component {
constructor(props) {
super(props);
this.handleToggleActive = this.handleToggleActive.bind(this);
}
handleToggleActive(userId) {
console.log(userId);
}
render() {
return (
<ul className="user-list">
{this
.props
.users
.map(user => (
<User key={user.id} user={user} handleToggleActive={this.handleToggleActive} />
))}
</ul>
);
}
}

React/ ESLint - JSX props should not use arrow functions

You can refactor button into its own component:

class MyButton extends Component {
static propTypes = {
language: PropTypes.string.isRequired,
};

onClick = () => console.log(this.props.language);

render() {
const {language} = this.props;
return (
<button onClick={this.onClick} type="submit">
{language}
</button>);
}
}

and then in your LanguageDropDown class, use MyButton like this:

class LanguageDropdown extends Component {
...

render() {
return (
<div>
{this.props.languages.map(lang => <MyButton key={lang} language={lang}/>)}
</div>
)
}

...
}

A couple of additional things:

  • You have a typo onCLick should be onClick
  • You need a key for repeated items

Formik throwing Error: JSX props should not use functions in React

<Field name='name' validate={() => validateFunc}>
{({ field, form }) => (
<FormControl isInvalid={form.errors.name && form.touched.name}>
<FormLabel htmlFor='name'>Default</FormLabel>
<Input {...field} id='name' placeholder='name' />
<FormErrorMessage>{form.errors.name}</FormErrorMessage>
</FormControl>
)}
</Field>

maybe you can try this to fix your problem



Related Topics



Leave a reply



Submit