1. Introduction
Hello everyone though React
‘s Hooks
has been around for a while but recently I have had a chance to try it out more in the project so I want to share this article with you about a Some of the things I learned about some of the Hooks
functions I learned
2. React Hook
a. useState
Perhaps for those of you who have read about Hook
in React
, this is one of the two most basic Hook
introduced among the Hook
. useState
as React
‘s document introduces it has the same functionality as state
in class Component
. For me, this Hook
is quite useful because since it is used, I hardly need to create class Component
anymore. If you previously had a component sidebar like this:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">const</span> <span class="token function-variable function">Sidebar</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> <span class="token operator"><</span> ul <span class="token operator">></span> <span class="token operator"><</span> li <span class="token operator">></span> Menu <span class="token number">1</span> <span class="token operator"><</span> <span class="token operator">/</span> li <span class="token operator">></span> <span class="token operator"><</span> li <span class="token operator">></span> Menu <span class="token number">2</span> <span class="token operator"><</span> <span class="token operator">/</span> li <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> ul <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> |
For the first purpose, this Sidebar
will always be displayed, you just need to write as above and import it to use. But later, you want to be able to collapse this Sidebar
to have more screen area for the main content, we will need to update it. Before the days of Hooks
, we would have to refactor this component back to class Component
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <span class="token keyword">class</span> <span class="token class-name">Sidebar</span> <span class="token keyword">extends</span> <span class="token class-name">Components</span> <span class="token punctuation">{</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> isCollapsed <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">handleToggleSidebar</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">setState</span> <span class="token punctuation">(</span> prevState <span class="token operator">=></span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> isCollapsed <span class="token punctuation">:</span> <span class="token operator">!</span> prevState <span class="token punctuation">.</span> isCollapsed <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> isCollapsed <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> state <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div className <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> isCollapsed <span class="token operator">?</span> <span class="token string">'hide'</span> <span class="token punctuation">:</span> <span class="token string">'display'</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span> <span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span> button onClick <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> handleToggleSidebar <span class="token punctuation">}</span> <span class="token operator">></span> Collapse <span class="token operator"><</span> <span class="token operator">/</span> button <span class="token operator">></span> <span class="token operator"><</span> ul <span class="token operator">></span> <span class="token operator"><</span> li <span class="token operator">></span> Menu <span class="token number">1</span> <span class="token operator"><</span> <span class="token operator">/</span> li <span class="token operator">></span> <span class="token operator"><</span> li <span class="token operator">></span> Menu <span class="token number">2</span> <span class="token operator"><</span> <span class="token operator">/</span> li <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> ul <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Before the time of Hook
, I used to have to do this because whenever I code, I still follow the “ideal” that I read somewhere online to always prioritize the function component
. However, since there are Hooks
, instead of having to revise as much as above, I simply need to do the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">const</span> <span class="token function-variable function">Sidebar</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> isCollapsed <span class="token punctuation">,</span> setCollapse <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">handleToggleSidebar</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">handleToggleSidebar</span> <span class="token punctuation">(</span> <span class="token operator">!</span> isCollapsed <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div className <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> isCollapsed <span class="token operator">?</span> <span class="token string">'hide'</span> <span class="token punctuation">:</span> <span class="token string">'display'</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span> <span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span> button onClick <span class="token operator">=</span> <span class="token punctuation">{</span> handleToggleSidebar <span class="token punctuation">}</span> <span class="token operator">></span> Collapse <span class="token operator"><</span> <span class="token operator">/</span> button <span class="token operator">></span> <span class="token operator"><</span> ul <span class="token operator">></span> <span class="token operator"><</span> li <span class="token operator">></span> Menu <span class="token number">1</span> <span class="token operator"><</span> <span class="token operator">/</span> li <span class="token operator">></span> <span class="token operator"><</span> li <span class="token operator">></span> Menu <span class="token number">2</span> <span class="token operator"><</span> <span class="token operator">/</span> li <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> ul <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
As you can see, it is much tighter than the previous version and still achieves the purpose we want.
b. useReducer
If you have ever used Redux
, it is not new to this concept. One of the developers of Redux
is Dan Abramov
who is currently a member of the React
development team, so maybe Dan
brought the name into React
‘s Hook
. useReducer
works the same way as the Reducer
you see in Redux
. useReducer
also takes two parameters which are our current state
and an action
that can determine how our state will change. To better understand, we will consider the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <span class="token keyword">const</span> <span class="token function-variable function">PostList</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> posts <span class="token punctuation">,</span> setPosts <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> loading <span class="token punctuation">,</span> setLoading <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> error <span class="token punctuation">,</span> setError <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">loadUser</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">setLoading</span> <span class="token punctuation">(</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> axios <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'some-post-url'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</span> <span class="token punctuation">(</span> response <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> data <span class="token punctuation">}</span> <span class="token operator">=</span> response <span class="token punctuation">;</span> <span class="token function">setPosts</span> <span class="token punctuation">(</span> data <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">setError</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">setLoading</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span> error <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">setLoading</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">setError</span> <span class="token punctuation">(</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token comment">// Some UI</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Talking about the script above, we will have a function that when called into it will perform a call to the API to get the article list and display it for us. And for the best experience, while waiting for the results from the API we will display a UI that is loading is decided by the state loading
as you see above. In case of successfully retrieving the data, the loading
will return to false
and hide the loading UI to display the list of posts for you. In case of error, the error
will be true
and you may display an error message. In the above scenario, when your state
has many properties and the properties will change according to the same action group, we can use useReducer
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <span class="token keyword">const</span> <span class="token function-variable function">postReducer</span> <span class="token operator">=</span> <span class="token punctuation">(</span> state <span class="token punctuation">,</span> action <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span> action <span class="token punctuation">.</span> type <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token string">'LOADING'</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> posts <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> loading <span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> error <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token string">'LOAD_SUCCESS'</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> posts <span class="token punctuation">:</span> action <span class="token punctuation">.</span> posts <span class="token punctuation">,</span> loading <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token string">'LOAD_ERROR'</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> posts <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> loading <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token punctuation">:</span> action <span class="token punctuation">.</span> error <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">PostList</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> state <span class="token punctuation">,</span> dispatch <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useReducer</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> posts <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> loading <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">loadUser</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> <span class="token string">"LOADING"</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'some-post-url'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</span> <span class="token punctuation">(</span> response <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> data <span class="token punctuation">}</span> <span class="token operator">=</span> response <span class="token punctuation">;</span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> <span class="token string">"LOAD_SUCCESS"</span> <span class="token punctuation">,</span> users <span class="token punctuation">:</span> data <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span> error <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> <span class="token string">"LOAD_ERROR"</span> <span class="token punctuation">,</span> error <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token comment">// Some UI</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
With the above example, you can see why it is called useReducer
because it upon themselves like a cousin to Reducer
of Redux
. With the above example, you might think that using useReducer
seems to take more code than useState
as originally. However, in case your state
is a complex object containing many classes and your actions have only partially changed, then useReducer
is what you need instead of creating dozens of useState
. This is understandable because Redux
also uses it to make store
changes
c. useEffect
When I first read about the uses that this Hook
can do, I found it quite “magical” because I heard it would replace both componentDidMount
, componentDidUpdate
and componentWillUnmount
. But in fact when working, you should not think that it will replace the above functions, but simply understand that the function is “useEffect will run after every time your component re-render if it meets the conditions you set. when component is unmounted “. That is all you need to remember, not replace the lifecycle above. Consider the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">const</span> <span class="token function-variable function">UserInfo</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> user <span class="token punctuation">,</span> setUser <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">useEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> axios <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`user-info-</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> someUserId <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</span> <span class="token punctuation">(</span> response <span class="token operator">=></span> <span class="token function">setUser</span> <span class="token punctuation">(</span> response <span class="token punctuation">.</span> data <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> someUserId <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token comment">// User info UI</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
With the above example, we see inside useEffect
there will be a function used to call the API to get the user information with id id someUserId
. In addition useEffect
also accepts another array under the name of dependancy
or you have many articles called deps
for short. Basically as its name implies, the function you pass in useEffect
will be called if one of the components in your deps
changes. It is as simple as that. However, you should note that if your deps
are an object, it is likely that your useEffect
will be called continuously because it will compare the reference rather than the value. Add another tip for you when using useEffect
as follows. Suppose we modify the above code to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">const</span> <span class="token function-variable function">SomeRemoteList</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> data <span class="token punctuation">,</span> setData <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">fetchData</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// So something to fetch data</span> <span class="token punctuation">}</span> <span class="token function">useEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">fetchData</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token comment">// User info UI</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
If you intend to write the API call function out of useEffect
and call it in useEffect
, I recommend not. The functions you use in useEffect
, you should define it always like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">const</span> <span class="token function-variable function">SomeRemoteList</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> data <span class="token punctuation">,</span> setData <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">useEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">function</span> <span class="token function">fetchData</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// So something to fetch data</span> <span class="token punctuation">}</span> <span class="token function">fetchData</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token comment">// User info UI</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Why should we do the above because firstly in case your function uses or depends on some other parameter then you will probably miss the declaration of it in the deps
leading to confusing bugs. In addition, moving the function into the useEffect
as mentioned above will help you later when looking at this effect
will quickly grasp all of what it does because it is like writing fully packaged into a small module in the component of you so.
3. End of lesson
My article here is the end. Because the fact that Hook
still quite new and does not really have any best practice guide, all I share above is also from my personal experience combined with some readable data. If you find something inappropriate or incorrect, please comment right below so I can update my knowledge. Finally, thank you for reading the article and remember to leave an upvote