Now, this one is sneaky, because I've noticed in our use case as well, we had a component on which we had two different listeners. One was a click listener, and the other was the listener on key press, which would perform the same action, but they were spread apart. And because of which, they were calling the, let's say, primary action using two different functions. Happens a lot when you have a large code base, right? So what ended up happening is the mouse click, the listener for that, it was using values from a different location, and the enter key press was using from a different location, which is fine, right? They should be getting the same values, they'd call their own functions, perform their side effects, and then would perform the common action. But the issue that was there was on the key press, the value that was getting, it was reading from a state, and you should know, again, the same mental model. Whenever you define a listener or anything in React, it will capture the value of the states that exist at that particular point. Right? So when the listener was registered, it captured the values at that point. So when it executed, it ideally should have taken the latest values, but it didn't, right? It took the old values. And it was something that we didn't notice because the side effect to it was mine. But later on the line, when we realized, that's when we figured out that, okay, this can impact. The impact could be worse, right? Because you might have a lot of actions being performed on it, maybe some value count, or maybe some analytical data, and that will be corrupted, and you might not realize it. So let's see an example.
So here, if you see, I have just a button which increments a counter, and I have a listener added on enter. Let's say I increment it to 6 and I press enter. So you see, the enter key shortcut saw the value 0, but the actual state was 6. Why? I'll show you the code. It's pretty standard, right? I just have a state and use effect of a handler which on enter key press, would lock the value. Do you see the error? The error is out here in the dependencies, I do not have anything mentioned, right? It's an empty dependency array. So it basically means that this use effect will run only once when the component mounts. When the component mounts, the value of the state is 0. So no matter how many times I increment it, the value of state will change, but this function, the function that we define within use effect, it will always, always see 0, no matter what. What's the fix? There's a lot of ways we can fix it. One such way is simply using a ref, right? There's two ways, actually, many more to be honest, but a clean way that I figured is use a ref. So if you see, I've created a ref, right? And in use effect, I've just put a dependency on the state, whenever it changes, the value of the ref will change, right? So when you press enter, it will basically just take that value. Another option could be to change the dependency array and add the state out here, but the reason that it's not recommended here is that every single time the value of this state changes, the listener will be destroyed and a new listener will be created. That's a lot of extra work. Just use refs for this exact purpose. Let me show you now. Here we're doing the fixed code, that is this one. So let's say I increase it to six and I press enter, you see, it reads the correct value, it's as simple as that.
Comments