The Phantom Event Argument

I just completed the “Create a Controlled Input” exercise in the React track using the code below. However, I do not understand how this code passes the tests due to the event parameter. The argument is not declared in the render method when the handleChange method is called, and as far as I can see, there is nothing that connects this.state.input to event.target.value.

If anyone could clarify how the connection is being made to me I would be very grateful.

jsx

class ControlledInput extends React.Component {
constructor(props) {
  super(props);
  this.state = {
    input: ''
  };
  this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
  this.setState({
    input: event.target.value
  });
}
render() {
  return (
    <div>
      <input value={this.state.input} onChange={this.handleChange}/>
      <h4>Controlled Input:</h4>
      <p>{this.state.input}</p>
    </div>
  );
}
};

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.61.

Challenge: Create a Controlled Input

Link to the challenge:

Well the input calls handleChange() when there is on a change, then the onChange calls setState({}) to the input value.

I understand that connection, yes, but the current code for handleChange has the setState contents as event.target.value. Just looking at the code, I do not understand where this method is getting the argument for event from, because it isn’t declared anywhere else in the code.

I understand that this.state.input and event.target.value are somehow connected, but because I don’t yet understand how, I do not feel capable to use this interaction in the future.

If I wrote this line like this:

<input value={this.state.input} onChange={(event) => this.handleChange(event)}/>

Now do you see how it is done. That is what happens when you put the function in the curly braces.

2 Likes

I would do this all the time, until I discovered the other way which is just to pass it in. To get comfortable, pass regular arrow functions until you start seeing connections.

You

So, in vanilla javascript (without any frameworks or libraries), events happen all the time. mouseover, click, keypress, blur, change, submit… events are constantly firing off. The browser is NOISY with events. And each time those things happen, the thing that they happened TO creates an Event object, and triggers that event on itself, and bubbles that up to each of its ancestors in turn.

So a submit button might fire off a click event, and it would create an Event object, telling what triggered the event, and a lot of custom details about that Event. In this case, you have an input element. That input is being changed, and each time its value changes, it fires off a change event.

We can handle those events, by writing event handlers. An event handler is a specific type of function: it is a function that takes, as its parameter, that Event object. We might name it differently (you’ll often see it named as e or evt or event), but they all take that one object, that implements a very specific interface.

So when react has an onchange attribute on an input, that’s an event handler. It is made to receive the Event, with a well-defined interface (that you can read about here: https://devdocs.io/dom/event), and to do something with that event.

In this case, you’re looking at a particular attribute on the Event object: Event.target (within your handleChange function, as the Event object has been assigned to the variable event, it’s event.target). That is the element that triggered the event itself, as it is in the DOM at the moment the event was triggered. event.target.value is the current value of that input element, at the instant the event happened.

So when we use event, as you are, you’re writing an Event listener, and you’re properly handling the event object. You are pulling data from that event object, and you’re updating the state of your component based on that.

2 Likes

@razzakammar_nano @snowmonkey Thank you both very much, I think I understand how this works now.
I wasn’t aware that the creation of the event argument was automatic, or that this.handleChange functioned as shorthand for (event) => this.handleChange(event), but these two points make it much clearer.

1 Like

not really

it’s more like the difference between

arr.filter(el => Boolean(el));

and

arr.filter(Boolean);

in both cases you are passing a function to the argument. In the first case you are passing a function that call a function and returns it, in the second you are just passing that function directly to the method

in both cases the function Boolean is used by the filter method, they are both valid, in the second case there is a step less

2 Likes