Solving Event Handling Errors in React
Ridhik Govind
Posted on April 25, 2021
Event handling in React is one of the basic things you learn when you start learning React. Some example are: 'onClick', 'onSubmit', 'onChange' etc, and if you are coming from a Vanilla JavaScript path, handling events in React will feel a lot easier. But it does come with some basic understanding of the JSX syntax and using React state.
So let's get started ? As always starting with our end goal and how we would be reaching that goal.
GOAL: To change the word from 'heyy' to 'byee' on the click of the button
METHOD: Using an event handler and React state
below is a basic layout of how the app is structured
export default function App() {
const[word,setWord] = useState('heyy')
return(
<div>
{word}
<button>Click here</button>
</div>
)
}
CASE - 1: Doing it the wrong way.
export default function App() {
const[word,setWord] = useState('heyy')
return(
<div>
{word}
<button onClick="byee">Click here</button>
</div>
)
}
Now this isn't what people do in real life but I just wanted to show you the error which we will get if we do this: Here's the error:
Error
Expected `onClick` listener to be a function, instead got a value of `string` type.
Why ? Because event handlers must always be a function or a reference to a function. Here the button will not work because the event handler here i.e onClick
is set to a string.
CASE - 2: Doing it the confusingly wrong way
<button onClick={setWord('bye')}>Click here</button>
Now look at the above code. Logically speaking when one looks at this code it is simple - you have an event handler which is set to setWord
function, inside which we have 'bye' argument, hence its a function call. So if a user clicks this button, the state will be updated. Right ?
Simple answer is Yes, the state will be updated BUT with a BIG error that goes like this:
Error
Too many re-renders. React limits the number of renders to prevent an infinite loop.
So why do we get this 'too many re-renders' error ? Well, for that let's kick back some React basics.
Now in React curly braces like this one {}
are a special JSX syntax which are used to evaluate some JavaScript variable, function or any code that has a value.
So if we look at the code above in this Case, we can see that we have written onClick={setWord('bye')}
. The problem with this is that at the very first time the app runs (i.e first render), this curly braces gets executed regardless of whether it is attached to an event listener or not. That is one feature of this special curly braces. Don't believe me ? try the below code:
export default function App() {
const[word,setWord] = useState('heyy')
return(
<div>
{word}
<button onClick={console.log('bleh! I just ran just like that')}>Click here</button>
</div>
)
}
Did you see that the output got logged at the first render itself without even clicking the button ? You bet !
Note: But if we click the button, nothing happens. This is because like we said curly braces is executing the console.log function, and we know that a function should return something. But since, here no value is being returned, undefined
is being returned, thus nothing is logged out.
Now, I said that the 'STATE WILL BE UPDATED' in this case. But you wont be able to see because the error is being displayed on top of everything. But here's one way to debug you code and see what really happens under the hood. Try this code instead:
export default function App() {
const[word,setWord] = useState('heyy')
+ console.log(word);
return(
<div>
{word}
<button onClick={setWord('byee')}>Click here</button>
</div>
)
}
Now check your console and you will see that the error has happened because the state has been updated too many times. Now combining the basics of curly braces, we can understand that this is what actually happens:
- 1st RENDER - curly braces runs the code inside it whether if it's attached to an event listener or not, state gets updated to 'byee', starts the 2nd RENDER
- 2nd RENDER - again same thing happens: curly braces are executed, state gets updated to 'byee' again, starts 3rd RENDER and it goes on..and on.. till React is like "Okay dude, enough is enough,this is too much, lemme show you some errors".
CASE - 3 : Some better ways to use an event handler
Better way - 1: Defining event handlers directly in the button's attribute
<button onClick={() => setWord('bye')}>Click here</button>
Basically, by setting the event handler to an arrow function which points to a reference, no function gets called until and only when the button is clicked.
When we do it this way, we are like "Hey onClick, I have given you one function, which contains some activity to be done. ONLY DO IT when I click something on screen.
Better way - 2: Cleaner way to do it.
Not many people prefer to do it the first way because sometimes, we have to add more than one activity to this function. So we can do it this way:
export default function App() {
const [word, setWord] = useState("heyy");
const handleClick = () => {
setWord("Byee");
};
return (
<div>
{word}
<button onClick={handleClick}>Click here</button>
</div>
);
}
Here, we have created a separate function that does something i.e change the state, and have attached this function to the event handler.
Conclusion:
Making sure you understand the bare basics of React is really important.You can get away with these tiny errors by making some adjustments, but in the long term its good to know what actually causes this error. Thanks for reading and hope you have learned something new today 😊. Byee !
Posted on April 25, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.