React useUndo hook
Tags: javascript, react, webdev, tutorial
Published: 2021-09-05 14:19:43

I am totally new in web development and this is my first blog, any sorts of suggestion or comments is welcome and that will help me to learn and grow.
So lets start with the `useUndo` hook.
Last week in our organization came with a requirement that we need to have a card that will have two options `Accept` and `Decline`, and after selecting any one of the option we will be giving the user a time period of let say 10 sec and with in this period they can undo their action.

``` eg ---> ```
![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phnytp0mmeirpkxkw0iv.png)
 

If they accept/ delete

![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7koywghmmdg8gpzeeli5.png)
 

So what i thought is to make a undo function which can help me with with this and also if i would like to use this undo function anywhere anywhere i will use it. So i came up with an `useUndo` hook, which was possible with `React lifecycle`
 

so lets discuss with the code and how i had implemented it.

First i will show the full code and then i will break it in different part and discuss about each of them.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7xqo4bml7pliglsnca59.png)
 

First i have used `useState` react hook to
1. Invoke the undo function
2. store the timeout id
3. to check if the method execution is finished or not.

![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z22w4uxatnfrui19yxfw.png)

Next is the `onUnload` event-lisitener function
![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kyet2f90rib2mhjbo8cx.png)

what this will do is it will throw and alert if you are trying to close the tab or window. We are doing this because as we are using setTimeout and clearTimeout so these are window scoped and each time we close or open a new tab a new scope is created so if we close the tab the the setTimeout which are web-api will be cleared from the call back queue and will not enter in the execution stack even after the time interval is over.
![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iypumlj4oszbwkusmsbx.png)

Hence we will listen for an `event-listener` i.e `beforeunload`.

Next the most important part according to me in this code is the `useEffect` part i.e

![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qatiwjpqt4rxralvgbk.png)
 
So what we are doing here is 
1. First we check if `invokeUndo` is true or not and if so we add an event listener `beforeunload` on window.
then we put our function inside the timeout which will be executed after 10000ms i.e 10s. Now the `setTimeout` web-api return a uniq number everytime you run it, which will be used to clear the timeout fucnction.

Inside the setTimeout we call the function which is `resolveMethod()` set the `undoTimerId` to null as the function  execution is finished, `setMethodExecuted` to true which will be returned value and while using the hook if we have any action to perform after execution can be done, &         `setInvokeUndo(false)` as the execution is finished.

Now the important part we need to do some clean-up on component-unmount so we will have a return statement in useEffect which will clear eventListener.

Now to invoke the undo we have invokeUndoMethod which will be a returned value and while using this hook we can use this.

we have an `undoMethod` which will perform the undo method i.e `clearTimeout`, setInvokeUndo to false.

![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g5y896e3ak629skiblcd.png)


Now we will have a final return statement

![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lk4mbrvicy0do4v172e1.png)
  
1. `undoMethod` to perform the undo action
2. `invokeUndoMethod` to invoke the undo or start undo method
3. `isMethodExecuted` this will tell if the method execution     is completed or not.


Now while using it.

![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ogujqi9mdqtdxer6e12i.png)


we can import this useUndo hook and pass inside the `onAcceptance` method we need to be executed after 10s.


That's All folks 😃

`Update ---> github repo link`

https://github.com/mishrabhavesh/useUndo