Question about the solution to this problem

Tell us what’s happening:
I have already solved this problem but there is a question that I still have. If I write the handleChange method as shown, without passing event as a parameter, the code seems to work fine but it fails the tests. Is there some missing functionality that I am not noticing? Is the event parameter optional for everything except passing the FreeCodeCamp.org tests? Please help me improve my understanding of this code.

Your code so far

// Add handleChange() and submitMessage() methods here
handleChange() {
this.setState({
  input: event.target.value,
  messages: this.state.messages
})
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0.

Challenge: Manage State Locally First

Link to the challenge:

event is a global variable. When you pass (e) => { } that’s just re assigning the variable event=e, if you don’t the local variable (event) is still available

Open a console and try this:

p = document.createElement("P")
p.style.height=20
p.style.weight=20
p.style.background="red"
document.body.appendChild(p)
p.addEventListener("click", () =>console.log(event))

Click on the element and see the output.

Idk the exercise, but I wouldn’t worry much either.

I don’t see how that could possibly work. Since event is undefined, you should get a null pointer exception and a crash. You at the very least need

handleChange(event) {

The method needs to accept that parameter and name it. The only other way would be if event were some kind of global variable, but I can’t even imagine how to make that work, and it would be bat crap crazy anyway.

Where sometimes people are redundant is in the onChange attribute. People will often write:

onChange={ (event) => this.handleChange(event) }

That is unnecessary, just creating an anonymous arrow function to wrap it. Since we are accepting the first parameter being passes and just passing it as the first and only parameter to our method, we can just do this:

onChange={ this.handleChange }

It will pass whatever it has to that method and it will map them to the parameter list in the method. But the method has to have a parameter list or it will just disappear into the ether.

I just tested it again by going back to this challenge, copying and pasting the solution code, and deleting the event parameter so that the only change is:

handleChange() {

The messaging app that the lesson builds works fine. There is no pointer exception or crash.

Can I see all the code please? I get a console full of errors when I do it, at least when I type in the input and the handler is fired.

class DisplayMessages extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: '',
      messages: []
    }
  }
  // add handleChange() and submitMessage() methods here
  handleChange(){
    this.setState({
      input: event.target.value,
      messages: this.state.messages
    })
  }

  submitMessage(){
    this.setState({
      input: '',
      messages: [...this.state.messages, this.state.input]
    })
  }

  render() {
    return (
      <div>
        <h2>Type in a new Message:</h2>
        { /* render an input, button, and ul here */ }
        <input onChange={this.handleChange.bind(this)} value={this.state.input}/>
        <button onClick={this.submitMessage.bind(this)}>Submit</button>
        <ul>
          {this.state.messages.map((x, i)=>{
            return <li key={i}>{x}</li>
          })}
        </ul>
        { /* change code above this line */ }
      </div>
    );
  }
};

This is simply the code from the solution to the challenge with the event parameter removed from the handleChange method. Removing the event parameter causes the tests to fail; however, there are no error messages and the messaging app in the preview window seems to function perfectly.

Yeah, that seems to work. My guess is that there is a global variable called “event”, that is invisible and behind the scenes, part of the FCC testing environment. But that is 1,000% not how it should work. In a real React app, that would crash.

Maybe I’ll look deeper and see if we need to create a bug.

And just for clarity:

    this.setState({
      input: event.target.value,
      messages: this.state.messages
    })

The line messages: this.state.messages doesn’t need to be there - any state props that aren’t changing don’t need to be set - setState does a shallow merge so it will just carry over.

Thanks for the help. I appreciate both of the explanations that I received regarding the global event variable.

Also, thank you for this clarification. When I first got the app working but the tests were failing. I looked at the solution and my first change was to add this optional line of text. I didn’t think I needed it and you have confirmed that.

Here is the type definition for the onChange attribute:

React.InputHTMLAttributes<T>.onChange?: (event: ChangeEvent<T>) => void

The first argument passed to the onChange event handler function is a React ChangeEvent object. You can name it whatever you like. If you don’t use the argument or give it a different name then event is interpreted as the global Window.event object.

According to MDN web docs:

The read-only Window property event returns the Event which is currently being handled by the site’s code. Outside the context of an event handler, the value is always undefined .

You should avoid using this property in new code, and should instead use the Event passed into the event handler function. This property is not universally supported and even when supported introduces potential fragility to your code.

Note: This property can be fragile, in that there may be situations in which the returned Event is not the expected value. In addition, Window.event is not accurate for events dispatched within shadow trees.

Your solution works in the browser because the global event object is defined. But the test environment does not run in the browser. Therefore, event is undefined, and the test fails.

2 Likes

Hmm, interesting, I didn’t know it existed globally. But yeah, it definitely shouldn’t be used - use the passed in event.

Nice research.

that particular exercise solution caused me a lot of pondering, on where the event comes from and while i figured out there must be some object stored, it still didnt make much sense. Thanks for the clarification!