reactjsevent-handlingsynthetic

Synthetic event doesn't work as expected in function component


I have 2 examples, one with class component and one with function component doing exactly the same thing. I'm using React 16.13.1. I know that if you don't persist the event you will get an error saying that the event target is null. This happens as expected in class component. In function component though, this isn't the case. What is the difference between them?

export class App extends React.Component {
  constructor() {
    super();
    this.state = { text: '' };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    console.log(event.target.value);
    this.setState(() => ({
      text: event.target.value
    }));
  }
  render() {
    return (
      <div>
        <span>Text: </span>
        <input onChange={this.handleChange} value={this.state.text} />
      </div>
    );
  }
}


const App = () => {
  const [state, setState] = useState({ text: "" });
  const handleChange = (event) => {
    console.log(event.target.value);
    setState({
      text: event.target.value,
    });
  };

  return (
    <div>
      <span>Text: </span>
      <input onChange={handleChange} value={state.text} />
    </div>
  );
};

Solution

  • This all comes down to the timing for when this.setState() and setState() is called. In your class component, the additional arrow function declaration inside this.setState causes an additional delay that makes the call take longer than the useState hook in the functional component. If you wrap the setState() call in your functional component with a setTimeout of 100, you get an error as expected. Also, if you modify the setState call to this.setState({ text: event.target.value }) in your class-based component, you no longer get an error. Finally figured that out with some inspiration from the official React docs.