Warning: This synthetic event is reused for performance reasons happening with <input type="checkbox" />

JavascriptReactjsReact ReduxFrontend

Javascript Problem Overview


I've been working on a simple react-redux todo example for a class and I came across several warning messages that show in the console everytime I check and uncheck a checkbox input.

You can see the warnings in the following images.

Warning Error Image

I also did a google search for the warning message but couldn't find any solution that works. Also, what stroke my attention was that it looks like it was trying to access every property of the native event, and DOM element.

This is the code for the presentational component that has the input checkbox

class TodoItem extends React.Component {
  state = {
    isChecked: false
  };
  handleCheckbox = () => {
    this.setState({
      isChecked: !this.state.isChecked
    });
  };
  render() {
    const { todos, onItemClick } = this.props;
    const { isChecked } = this.state;
    return (
      <div>
        <ul>
          {todos.map((todo, id) => {
            return (
              <li key={id} onClick={onItemClick}>
                <input
                  onChange={this.handleCheckbox}
                  type="checkbox"
                  checked={isChecked}
                />
                <label>
                  <span />
                  {todo.textInput}
                </label>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

export default TodoItem;

I uploaded the example on CodeSandbox as well: https://codesandbox.io/s/k0mlxk1yqv

If you want to replicate this error you need to add an Item to the todo List and click the checkbox to check and uncheck a couple of times.

If anyone has any idea why this warning signs keep appearing and how to disable them I would appreciate your input very much :)

Javascript Solutions


Solution 1 - Javascript

This happened because the event implicitly passed to onItemClick is used in an asynchronous context.
As Andre Lemay said, you should assign your needs to local variables and reference them.

In my case, I had this code:

handleInput = e => { // <-- e = synthetic event
  this.setState(state => ({ // <-- asynchronous call
    data: {
      ...state.data,
      [e.target.name]: e.target.value // <-- this was causing the warnings (e.target is in an asynchronous context)
    }
  }));
};

Then I changed it to:

handleInput = e => {
  const { name, value } = e.target; // <-- moved outside asynchronous context

  this.setState(state => ({
    data: {
      ...state.data,
      [name]: value
    }
  }));
};

Solution 2 - Javascript

I'd suggest trying two solutions:

First change

onChange={this.handleCheckbox}

to

onChange={() => this.handleCheckbox()}

If that won't work, in 'handleCheckbox' add event.persist(); Like this:

handleCheckbox = (event) => {
  event.persist();
  this.setState({
    isChecked: !this.state.isChecked
  });
};

Solution 3 - Javascript

This may be a little late, but I just came across the same problem and solved in a way that I think might be better than Adam Orlov's answer. I don't believe either answer is directly applicable to the asked question, but this comes up when googling about synthentic events and checkboxes so it's as good a place as any...

I believe Adam is correct in his belief that React will essentially clear all properties of the SyntheticEvent object (which makes sense, since React is telling us that it's reusing the object).

However, unless you need the entire object, I don't think calling event.persist() is the best solution, as according to the [documentation][1], that will remove the object from the pool (presumably they put it there for a good reason).

>If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

Instead of doing this, if you only need one or two values from the event object, you can just assign those to local variables, and then reference the local variables inside your own function, like this:

<input type="checkbox" onChange={(event) => {
    let checked = event.currentTarget.checked; //store whatever values we need from from the event here
    this._someOtherFunction(checked)
} />

In this way, you don't have to restructure your code in any way to avoid doing anything async that relies on event data, and you also don't have to worry about potential performance impacts as you allow React to do what it wants with the event pool. [1]: https://reactjs.org/docs/events.html

Solution 4 - Javascript

Similar problem here though my setup is, functional component, Material UI <Textform /> input.

The guy above that mentioned event.persist();, thank you that worked for me, but the first suggestion had no noticeable affect, not sure if thats because Im using functional components and not class components. (I dont use class components anymore, only functional with hooks)

Also note the warning info suggested to use event.persist(). My issue was I was capturing form input using onChange and storing input into my state, after about the second or third character it would throw errors and also crash my app.

Before:

    const handleChange = (e) => {
    
    setState((form) => ({
      ...form,
      [e.target.name]: e.target.value,
    }));
  };

After:

    const handleChange = (e) => {
    e.persist();
    setState((form) => ({
      ...form,
      [e.target.name]: e.target.value,
    }));
  };

So it appears this is the correct solution to a similar issue, while I was not using a checkbox, I was using a form input, a Material-UI <TextField />. I can remove the single line of

e.persist();

and the code will fail again, add it back, everything is good no crashing no warnings.

Solution 5 - Javascript

for the ones that came to this problem with react native.

i face this problem on a navigation

PersonalProductsScreen.navigationOptions=({navigation})=>{
const handleEditButton=navigation.navigate.bind(this,"EditProduct")
return {
    headerTitle:"My Products",
    headerRight:<CustomHeaderButton 
    iconName="ios-add"
    title="Add"
    iconSize={26}
    color={colors.bright}
    onPress={handleEditButton}
    />
}

}

pay attention to the method i used . I was trying to bind the navigate method.

This is the refactor:

const handleAddButton=()=>navigation.navigate("EditProduct")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRaymi View Question on Stackoverflow
Solution 1 - Javascriptw35l3yView Answer on Stackoverflow
Solution 2 - JavascriptAdam OrłowskiView Answer on Stackoverflow
Solution 3 - JavascriptAndre LemayView Answer on Stackoverflow
Solution 4 - JavascriptEric HendrixView Answer on Stackoverflow
Solution 5 - JavascriptFSBALBUENAView Answer on Stackoverflow