React interview questions - Counter questions (react hooks)

A walkthrough of counter component interview questions using React hooks. Covers why calling setCount twice only increments once, how functional updaters guarantee sequential updates, useEffect cleanup pitfalls, and pause/resume logic with state management.
Chapters
Hi guys, we're gonna explore different questions on counter in React. Let's get started. So let's see simple questions. So, um, let's have a counter. Let's store it in const count and setCount. And so we have a counter and, uh, yeah, and we want to increment it and It will be our increment function and we want to decrement it. And now we want to have some— to display this counter like so. Counter, just print and display it here as count. Okay, so now we have counter that started with 0. And now we can have buttons that we increment and we decrement the counter. So let's, let's go ahead and try to increment it. So we incrementing it and we decrementing it, and it looks like it works. And let's say we want another button of and decrement— increment twice. incrementTwice. Okay, and we have function of incrementTwice, and I'm gonna have and create a function of incrementTwice here. Yeah, but I'm not gonna use count 2, I'm gonna use twice increments, so it should be, should be good. I'm incrementing once and once and another time, so I incremented it twice. Okay, so what's gonna happen when I increment it? It's only incrementing once. Hmm. Let's make it a bit bigger, so I call it h1, uh, so you can see the content. Yeah, just like so. Okay, so let's refresh it and say, okay, I'm incrementing twice, but it's only incrementing once. Why, why is that happening? So why is that happening? So let's see to this function. How does React work? So just to show it more clear, I will just replace two of this function with increment because this is what, what it is. So what's happening in React in this function, it registers the actions it needs to set. So it looks at counter. What is counter? Counter is let's start with 0. Counter is 0 plus 1, so I need to set counter to 1. And the second action, I need to set counter— counter still is 0, okay? It's still 0 because none of it is applied. It's just, just registering the action. So now it's still 0 plus 1. So at the end of this function, it just set count to 1 twice. This is what is happening. So how can we prevent this from happening. We can use a function in setCount. So we can leave this increment and we can just use function of count. It receives previous value and set to the new value. If it's maybe confusing with the count, I can say it receives c and set c 1. So in this case, what is happening is it will register, and it will register, let's, let's take it here again. So it will register first time, okay, previous value is what? 0. 0 1, I'm setting to 1. And the next one, it checks the previous value. So it needs to take the previous value. So if this action finished, then the value will be 1. But this function will take, okay, what is the previous value? It's 1, and then it's add 1 to it. So in this case, yes, in this case, if I increment twice, I will get 2 and then 4. So, um, and in this case also we are not— there is no dependency because it receives a function. It's not dependent on count like here. Here I'm dependent on count, and every time count is changing, this function will be created again. Okay, and we need to update this function anyway because of, because of we don't use useCallback, so they will be created on every re-render. But if I would use here, for example, useCallback function, then in this case I will have no dependencies. Okay, I have no dependencies because setCount is, is not changing and I don't have, have no dependencies. But what's going to happen on decrement if I use callbacks? So if I use useCallback And in this case, my dependency array won't be empty. Why? Because I'm dependent on count, so I will have to add count here. So anyway, this is a good way to use state, is always to take a previous state and then change it unless you have some dynamic calculation of the state. But if we're talking about A new state is dependent on previous state. It's always a good idea to do that. So what we check is we check we can increment and we can decrement and we can increment twice. So all of it is work. Okay, what other questions can we ask about count? So there is a, a question. Okay, can you make a counter that increment itself every millisecond? And you say, yeah, I can. So let's, let's do that. Let's— I'm, I'm just gonna, I'm just gonna close, close that, and so it will not, not confuse us. Okay, so for that, we want to use a useEffect, useEffect. And in this useEffect, we're gonna, um, we're gonna do a setInterval because we want to increment counter every, every millisecond. So we have interval, setInterval, um, every millisecond. And but what we need to do is we need to also, when the component is unmounts, um, I need to do clearInterval. And I'm gonna do this only, um, onMount. Um, so our counter is running. We can see it's increasing and that's good. But let's see what happens if we, in this case, we use the functions that depend on previous value, right? But let's see if we didn't use it, if we didn't use the function. What, what it means is that count 1. So what's, what's gonna happen in this case? In this case, it's rendered only once, and then I'm not dependent on the count, counter, so it doesn't, it doesn't work. So in this case, we need to put a dependency array, counter in our dependency array, and, and then it works. But what is happening is that every time the count changes, so every millisecond, we're setting new interval and clearing new interval. As much as, as well, we could use just setTimeout in this case, but we don't want to set interval and clearInterval every time the count changes. So, um, it's a good idea to use a function here In, in, in the case we're using a function, then setInterval and clearInterval set only, only once, and then onUnmount, but we're not unmounting right now, but it happens only once. So there is another question of this sort that can be asked you about. Okay, can you do that so you will have only one setInterval, but you have to use count. You have to— you cannot use a function in setCount. It's a real question that can be asked and was asked. I just don't remember which place, but this question can be asked. Um, so okay, so I want to setCount, but I don't want to do setInterval every time the count changes. So I cannot put count in the dependency. So what, what can I do? Well, I can, I can store count in, in a value, in a using useRef const. So we'll say prevCount. We're gonna create prevCount that receives count, okay? And then In this case, so what we do is, uh, we just instead of using count here, we're using prevCount current because this is ref, refCount current 1. And after we do that, we also update our prevCount to be increased to the new value. Okay, as much as like, maybe, maybe it's a bit ugly, but you can also do this. It will be more clear. const newCount is equal to this, and then we say this gets newCount, newCount, newCount, and my current count equals newCount, newCount. Okay, so let's go ahead and refresh it. And what's happening? Our counter is working. We set interval only once and we didn't use a function, a function passing to the useState hook that we created. Okay, so This is how we solve it. And also you can obviously do that another way. Another way to do it is not to store the value, but if you asked if there is other way to do it. So another way to do it is if you asked, do you know the other way? So say yes. You still can use, you still can use ref, but you're using ref as a reference to, to the component. So for example, const countRef, and I'm, I'm not setting count in this case, just setting null. Why? Because my countRef, it will be the reference to my count. So I put ref here and there is my count. As much as, as well, I, I, I doesn't have to, I don't have to read the count, I can just put 0 here. Okay, so it starts with 0 and then on every interval I'm not using also prevCount, so we can see that. And what we can do is we can do our countRefCurrent.textContent, but I'm not using count as you remember, so I cannot use count here. But I'm, I'm taking the text content, I'm converting it to the number, and I'm adding 1 to it. Okay, so I'm directly, directly interacting with the DOM here. So we can see our counter is running. Yes, and we're setting only one interval. And if we want to check the amount of renderings, so we can just add useEffect. useEffect that just tells us about mounts and unmounts, and we don't pass— I'm not passing anything here, and I just want to console.log useEffect, and on return I want to say cleanup and close it. Yeah, so useEffect, render, and cleanup. Ah, just cleanup. Yeah, okay. Um, so what's happening we have only one render, so it's not re-rendering. And why? Because we directly using the DOM element. I'm not using count at all, so I can, I can even close it and everything works. My counter working and everything is working. So, but it's, it's a question that you need to know that it is possible. Is it useful? Sometimes there are some cases, but you need to be aware some applications are very complex and you need to be aware of all the possible things you can do. Okay, so let's, let's go back to the, uh, to React counter. And so I'm gonna use count here again, count, and we're gonna check the renders. In this case, if I use count here and I'm not gonna use this, I'm gonna use setCount, setCount, but not this, but just count 1. Okay, and we want to see the re-rendering, so we can see here that every time if it's dependent on count, it re-renders as we saw, and also I have setInterval that happening all the time. So in case we don't want it, and so we use our function c, c+1, and I'm gonna, I'm gonna remove the dependency array. So let's see rendering in this case. Okay, so we have one-time setInterval, which is good, but we still have re-renders. Why is it happening? Because because of our state, the count is changing and we want to display it. So different than what we had when we used ref, it was not re-rendering. But you just need to know that different cases can be— in which cases it can be used. But also you need to know, to, to know all the possibilities, which is, which is good. Okay, so what other questions can we ask about the counter, and we can ask, okay, now I have this counter and I want to, I want to pause and then resume the counter. Okay, so we can, we can do that too. And so for that we need, we need some, something to interact with, to tell, um, to tell the user the ability to, to pause and resume. So create a button and we call it on pause, on pause. And let's go ahead and create the pause button. Well, it doesn't pause, but we want to know when to pause and when to resume, right? So we need a state for that. So For that, I'm gonna create a state const pause, setPause, and in the beginning it's false because we're not pausing anything. So what's gonna happen in, in my function onPause? I want to setPause to— I can do notPause, but we learned that we can do it with a function, so previous value of the pause to not previous value. Okay, so it's a boolean value. And now, um, and now also, um, I can also, I can also say, okay, if pause, if pause is true, if it's true, then resume and if it's false, then pause. Okay, uh, pause is not defined. Um, maybe just to refresh it. Okay, so let's just also close these logs because they might confuse you, and refresh that. Okay, so, um, we have a button pause. It obviously does nothing. Because we didn't add it to our counting interval. So we're gonna add it to our useEffect, obviously. So I'm gonna create the interval. I'm gonna put let interval, it's gonna be start and then I'm gonna do that. So I want to do interval only if it is not paused. Not paused. If I'm not paused, I want to start my interval. Okay, and I want— I'm dependent on pause. Obviously this property, I'm dependent on pause. So what's happening? I set setInterval, it's counting. I do pause, stopped. I see I had a clearInterval. Well, setInterval here does nothing. Well, we see the printing, but it should be inside because it didn't, didn't start it again. So the print is confusing. Let's start again. So I have counter that is counting. I do pause, I had clearInterval, and then when I hit resume, I have clearInterval and then setInterval again. So this is exactly what we want. We want it to stop and then resume from the same, same number. Yes, resume. And it counting, counting again. Well, that's all the possible questions I know about counter. And have a great day!
More from Happy

Design System Interview - Design System for a kanban board , Fullstack developer, 2024










