It can be quite fun with Custom Hooks in React.
Let's say we just think of, I want a company that can give me a countdown from 3 to 0, and then give me a way to reset the count.
So we could just write this:
exportdefaultfunctionApp(){const[count,reset]=useXYZCompany();return(<divclassName="App"><h1>{count}</h1><buttononClick={reset}>Reset</button></div>);}
That's simple enough. It does not do anything imperative. It follows the line that in React, a lot of things are just declarative... all the way down to when we need to have something imperative to make it work.
So let's say this XYZCompany uses an iPhone to do the job:
functionuseXYZCompany(){const[count,reset]=useIPhone();return[count,reset];}
For simplicity, we just make each level return the same count and reset function. We could change it so that the XYZCompany provides some extra functions instead of just a countdown number.
Likewise, the iPhone uses an iPhoneApp:
functionuseIPhone(){const[count,reset]=useIPhoneApp();return[count,reset];}
The iPhoneApp does the imperative thing. It uses useEffect to run something:
functionuseIPhoneApp(){const[count,setCount]=useState(3);useEffect(()=>{letintervalID;if(count>0){intervalID=setInterval(()=>{setCount(count-1);},1000);}return()=>intervalID&&clearInterval(intervalID);});functionresetFn(){setCount(3);}return[count,resetFn];}
which is to simply decrement the count. Note that this useEffect runs every time, and I notice this is the common style that React code is written: it just "do" and "undo", so that we don't have to worry about anything, such as thecount
being the same from the closure. Each time, it just "undo" the previous task, and "do" the new task (of setting up the timer). It is like mathematical induction: if we know this step is correct, then undoing it and redoing it at a different state is also correct, and therefore, everything is correct.
So we can see the code running at:https://codesandbox.io/s/gallant-cloud-177mn?file=/src/App.js
When we press the Reset button, it is to tell the XYZCompany to do a reset. And then XYZCompany uses the iPhone and tells the iPhone to reset. The iPhone in turns tells the iPhoneApp to do a reset.
We don't have to go that many levels down. We can directly useuseIPhoneApp()
in the main component, but it is just to show how it would still work after many levels down.
ThesetState()
is written so that when it updates any value, any user, all the way to the top, will be re-rendered (re-invoked). So App would call useXYZCompany, and then call useIPhone, and then call useIPhoneApp.
So that's the methodology: we just get back some value from our custom hook. It looks static, but don't worry about it. As long as somewhere down the line, if it has asetState()
, then it will "magically" get down to you, appearing to be "changing the static value", as in the case ofcount
.
A random text shifter
We can also make a random text shifter, so that it will randomly shift some text. The custom hook is calleduseShifter()
. The code:
functionuseShifter(){const[shift,setShift]=useState(0);useEffect(()=>{constintervalID=setInterval(()=>{setShift((shift)=>{if(shift<0)return-shift;elseif(shift>0)return0;elseif(Math.random()<0.1)return-Math.random()/9;});},33);return()=>intervalID&&clearInterval(intervalID);},[]);return{position:"relative",left:`${shift}em`,top:`${shift/3}em`};}exportdefaultfunctionApp(){constshifter=useShifter();return(<divclassName="App"><h1className="message"style={shifter}>Hello</h1></div>);}
Demo at:https://codesandbox.io/s/optimistic-hamilton-1u9dv
This is another custom hook for a morpher shifter:https://codesandbox.io/s/epic-forest-kqt1d?file=/src/App.js
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse