Hello brothers, it’s me again
Today, I stood up again to share with everyone a few things, this time some of my experiences with coding in the React project. We hope the article will be useful to everyone.
Do not know that while at work, have people ever encountered the following situations?
Too many props:
When we pass too many props to a single component it can be an indication that that component should be separated.
Then one more question arises: How much is too much ??? Yes, my answer is “Depending”. We may run into a situation where a Component is passed 20 props or more, when you encounter a situation like that and the task asks us to add another props, we’ll have to ask more questions.
Is this Component doing too many things ???
In my opinion, it’s like a function , a component should do the best of one task, so to do this, we should check if it can divide that component into many components or not? For example that component has incompatible props or it returns JSX from functions.
Should I only use a Component ???
Using only one Component is very good but what we often ignore is that all logic in that component is processed without splitting. I have an example as follows:
1 2 3 4 5 6 7 8 9 10 | <span class="token operator"><</span> ApplicationForm user <span class="token operator">=</span> <span class="token punctuation">{</span> userData <span class="token punctuation">}</span> organization <span class="token operator">=</span> <span class="token punctuation">{</span> organizationData <span class="token punctuation">}</span> categories <span class="token operator">=</span> <span class="token punctuation">{</span> categoriesData <span class="token punctuation">}</span> locations <span class="token operator">=</span> <span class="token punctuation">{</span> locationsData <span class="token punctuation">}</span> onSubmit <span class="token operator">=</span> <span class="token punctuation">{</span> handleSubmit <span class="token punctuation">}</span> onCancel <span class="token operator">=</span> <span class="token punctuation">{</span> handleCancel <span class="token punctuation">}</span> <span class="token operator">...</span> <span class="token operator">/</span> <span class="token operator">></span> |
Looking at the above component, we can see that all functions are handled in that component, but we can still improve this confusion by breaking down the processed components in this component. :
1 2 3 4 5 6 7 | <span class="token operator"><</span> ApplicationForm onSubmit <span class="token operator">=</span> <span class="token punctuation">{</span> handleSubmit <span class="token punctuation">}</span> onCancel <span class="token operator">=</span> <span class="token punctuation">{</span> handleCancel <span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span> ApplicationUserForm user <span class="token operator">=</span> <span class="token punctuation">{</span> userData <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> ApplicationOrganizationForm organization <span class="token operator">=</span> <span class="token punctuation">{</span> organizationData <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> ApplicationCategoryForm categories <span class="token operator">=</span> <span class="token punctuation">{</span> categoriesData <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> ApplicationLocationsForm locations <span class="token operator">=</span> <span class="token punctuation">{</span> locationsData <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> ApplicationForm <span class="token operator">></span> |
Okk after processing, now I have ensured that ApplicationForm has only one job of it is to send and destroy the data fields in the form. Child components can handle anything related to their part in the form. This is also a great opportunity for us to practice using React Context for parent and child communication.
Are we passing too much ‘configuration’-props?
In some cases, we should group the props together into an optional object, in case we want to change an option. For example:
1 2 3 4 5 6 7 8 9 10 11 | <span class="token operator"><</span> Grid data <span class="token operator">=</span> <span class="token punctuation">{</span> gridData <span class="token punctuation">}</span> pagination <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> autoSize <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> enableSort <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> sortOrder <span class="token operator">=</span> <span class="token string">"desc"</span> disableSelection <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> infiniteScroll <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token operator">...</span> <span class="token operator">/</span> <span class="token operator">></span> |
I think we should do the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">{</span> pagination <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> autoSize <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> enableSort <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> sortOrder <span class="token operator">:</span> <span class="token string">'desc'</span> <span class="token punctuation">,</span> disableSelection <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> infiniteScroll <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token operator">...</span> <span class="token punctuation">}</span> <span class="token operator"><</span> Grid data <span class="token operator">=</span> <span class="token punctuation">{</span> gridData <span class="token punctuation">}</span> options <span class="token operator">=</span> <span class="token punctuation">{</span> options <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> |
Incompatible props
We should avoid passing inappropriate props:
For example, when we create a common <Input /> with the task of handling text in the form, but after that, we may want to process the input of number.
1 2 3 4 5 6 | <span class="token keyword">function</span> <span class="token function">Input</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> value <span class="token punctuation">,</span> isPhoneNumberInput <span class="token punctuation">,</span> autoCapitalize <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> autoCapitalize <span class="token punctuation">)</span> <span class="token function">capitalize</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> input value <span class="token operator">=</span> <span class="token punctuation">{</span> value <span class="token punctuation">}</span> type <span class="token operator">=</span> <span class="token punctuation">{</span> isPhoneNumberInput <span class="token operator">?</span> <span class="token string">'tel'</span> <span class="token operator">:</span> <span class="token string">'text'</span> <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> |
As we have seen, the problem with this common is that the props passed to isPhoneNumberInput and autoCapitalize don’t make a lot of sense. We can’t capitalize the phone number right.
In this case, the only solution is probably to split it into many smaller parts. If there is still some logic to share, we can turn it into a custom hook:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">function</span> <span class="token function">TextInput</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> value <span class="token punctuation">,</span> autoCapitalize <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> autoCapitalize <span class="token punctuation">)</span> <span class="token function">capitalize</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token function">useSharedInputLogic</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> input value <span class="token operator">=</span> <span class="token punctuation">{</span> value <span class="token punctuation">}</span> type <span class="token operator">=</span> <span class="token string">"text"</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">PhoneNumberInput</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> value <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">useSharedInputLogic</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> input value <span class="token operator">=</span> <span class="token punctuation">{</span> value <span class="token punctuation">}</span> type <span class="token operator">=</span> <span class="token string">"tel"</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> |
Copying props into state
Let’s see the following example:
1 2 3 4 5 6 | <span class="token keyword">function</span> <span class="token function">Button</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> text <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> buttonText <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> text <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> button <span class="token operator">></span> <span class="token punctuation">{</span> buttonText <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> button <span class="token operator">></span> <span class="token punctuation">}</span> |
Passing this props text means we have given up on the text value being updated because if it is updated the component will continue to render the state’s initial value, which will cause them to We are more prone to bugs.
A more realistic example of this happening is when we want to get some new value from a prop and especially if this requires some slow computation. In the example below, I will run the slowFormatText function to format the prop text, which will take a lot of time to execute.
1 2 3 4 5 6 | <span class="token keyword">function</span> <span class="token function">Button</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> text <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> formattedText <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 operator">=></span> <span class="token function">slowlyFormatText</span> <span class="token punctuation">(</span> text <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> button <span class="token operator">></span> <span class="token punctuation">{</span> formattedText <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> button <span class="token operator">></span> <span class="token punctuation">}</span> |
A better way to solve this problem is to use the useMemo hook to remember the results:
1 2 3 4 5 6 | <span class="token keyword">function</span> <span class="token function">Button</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> text <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> formattedText <span class="token operator">=</span> <span class="token function">useMemo</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">slowlyFormatText</span> <span class="token punctuation">(</span> text <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> text <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> button <span class="token operator">></span> <span class="token punctuation">{</span> formattedText <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> button <span class="token operator">></span> <span class="token punctuation">}</span> |
Returning JSX from functions
We should not return a JSX from functions within a component.
For 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 26 27 28 29 30 31 32 33 34 | <span class="token keyword">function</span> <span class="token function">Component</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">topSection</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">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> header <span class="token operator">></span> <span class="token operator"><</span> h1 <span class="token operator">></span> Component header <span class="token operator"><</span> <span class="token operator">/</span> h1 <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> header <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">middleSection</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">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> main <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">></span> Some text <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> main <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">bottomSection</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">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> footer <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">></span> Some footer text <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> footer <span class="token operator">></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 <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token function">topSection</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">middleSection</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">bottomSection</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</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> |
Although this code looks ok, it makes it difficult for me to reason about the code and does not encourage people to write this way. To solve this case, we should break it down into separate components.
Remember, not every time you create a new component you move it to a new file. Sometimes it is advisable to keep components in the same file if they are tightly coupled together.
Multiple booleans for state
We should avoid using multiple booleans for state representations.
When writing code, sometimes we will come across situations where we need to check the state of that component to see what state it is in to perform the function:
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">function</span> <span class="token function">Component</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> isLoading <span class="token punctuation">,</span> setIsLoading <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 keyword">const</span> <span class="token punctuation">[</span> isFinished <span class="token punctuation">,</span> setIsFinished <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 keyword">const</span> <span class="token punctuation">[</span> hasError <span class="token punctuation">,</span> setHasError <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 keyword">const</span> <span class="token function-variable function">fetchSomething</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 function">setIsLoading</span> <span class="token punctuation">(</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> url <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</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">setIsLoading</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token function">setIsFinished</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 function">catch</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">setHasError</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 keyword">if</span> <span class="token punctuation">(</span> isLoading <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> Loader <span class="token operator">/</span> <span class="token operator">></span> <span class="token keyword">if</span> <span class="token punctuation">(</span> hasError <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> Error <span class="token operator">/</span> <span class="token operator">></span> <span class="token keyword">if</span> <span class="token punctuation">(</span> isFinished <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> Success <span class="token operator">/</span> <span class="token operator">></span> <span class="token keyword">return</span> <span class="token operator"><</span> button onClick <span class="token operator">=</span> <span class="token punctuation">{</span> fetchSomething <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> |
In the above code, when the button is clicked, we will change the isLoading state to true and do the fetch request. If fetch success then we will change state isLoading to false, isFinish to true, and vice versa, set hasError to true if in fetch an error occurs.
Although the logic above can run well, it is very easy to confuse me, it can also fall into the case of ‘impossible state’, meaning that accidentally isFinish and isLoading both have true values at the same time.
A better way to solve this problem is to use enum :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">function</span> <span class="token function">Component</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> state <span class="token punctuation">,</span> setState <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token string">'idle'</span> <span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token function-variable function">fetchSomething</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 function">setState</span> <span class="token punctuation">(</span> <span class="token string">'loading'</span> <span class="token punctuation">)</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> url <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</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">setState</span> <span class="token punctuation">(</span> <span class="token string">'finished'</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">catch</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">setState</span> <span class="token punctuation">(</span> <span class="token string">'error'</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">if</span> <span class="token punctuation">(</span> state <span class="token operator">===</span> <span class="token string">'loading'</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> Loader <span class="token operator">/</span> <span class="token operator">></span> <span class="token keyword">if</span> <span class="token punctuation">(</span> state <span class="token operator">===</span> <span class="token string">'error'</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> Error <span class="token operator">/</span> <span class="token operator">></span> <span class="token keyword">if</span> <span class="token punctuation">(</span> state <span class="token operator">===</span> <span class="token string">'finished'</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> Success <span class="token operator">/</span> <span class="token operator">></span> <span class="token keyword">return</span> <span class="token operator"><</span> button onClick <span class="token operator">=</span> <span class="token punctuation">{</span> fetchSomething <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> |
By doing it this way, we eliminate the impossible and make the logic a lot easier. If using TypeScript, it is better as follows:
1 2 | <span class="token keyword">const</span> <span class="token punctuation">[</span> state <span class="token punctuation">,</span> setState <span class="token punctuation">]</span> <span class="token operator">=</span> useState <span class="token operator"><</span> <span class="token string">'idle'</span> <span class="token operator">|</span> <span class="token string">'loading'</span> <span class="token operator">|</span> <span class="token string">'error'</span> <span class="token operator">|</span> <span class="token string">'finished'</span> <span class="token operator">></span> <span class="token punctuation">(</span> <span class="token string">'idle'</span> <span class="token punctuation">)</span> |
Too many useState
We should avoid using too many useStates in a component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">function</span> <span class="token function">AutocompleteInput</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> isOpen <span class="token punctuation">,</span> setIsOpen <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 keyword">const</span> <span class="token punctuation">[</span> inputValue <span class="token punctuation">,</span> setInputValue <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token string">''</span> <span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> items <span class="token punctuation">,</span> setItems <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 keyword">const</span> <span class="token punctuation">[</span> selectedItem <span class="token punctuation">,</span> setSelectedItem <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 keyword">const</span> <span class="token punctuation">[</span> activeIndex <span class="token punctuation">,</span> setActiveIndex <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span> <span class="token punctuation">(</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token function-variable function">reset</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 function">setIsOpen</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token function">setInputValue</span> <span class="token punctuation">(</span> <span class="token string">''</span> <span class="token punctuation">)</span> <span class="token function">setItems</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">setSelectedItem</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token function">setActiveIndex</span> <span class="token punctuation">(</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">selectItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token parameter">item</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">setIsOpen</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token function">setInputValue</span> <span class="token punctuation">(</span> item <span class="token punctuation">.</span> name <span class="token punctuation">)</span> <span class="token function">setSelectedItem</span> <span class="token punctuation">(</span> item <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token operator">...</span> <span class="token punctuation">}</span> |
We have a reset function to reset all state and selecItem to update some state. Both use quite a bit of state coming from the useState location to do their job. Imagine, if we now have more actions to update the states, this will easily cause errors and difficult to control all the states. And to solve the above problem, I recommend using the useReducer hook:
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 36 37 | <span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token punctuation">{</span> isOpen <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> inputValue <span class="token operator">:</span> <span class="token string">""</span> <span class="token punctuation">,</span> items <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> selectedItem <span class="token operator">:</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> activeIndex <span class="token operator">:</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">reducer</span> <span class="token punctuation">(</span> <span class="token parameter">state <span class="token punctuation">,</span> action</span> <span class="token punctuation">)</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">"reset"</span> <span class="token operator">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span> initialState <span class="token punctuation">}</span> <span class="token keyword">case</span> <span class="token string">"selectItem"</span> <span class="token operator">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span> state <span class="token punctuation">,</span> selectedItem <span class="token operator">:</span> action <span class="token punctuation">.</span> payload <span class="token punctuation">}</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token keyword">throw</span> <span class="token function">Error</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">AutocompleteInput</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> 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> reducer <span class="token punctuation">,</span> initialState <span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token function-variable function">reset</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 function">dispatch</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> type <span class="token operator">:</span> <span class="token string">'reset'</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">selectItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token parameter">item</span> <span class="token punctuation">)</span> <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 operator">:</span> <span class="token string">'reset'</span> <span class="token punctuation">,</span> payload <span class="token operator">:</span> item <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> |
Large useEffect
Avoid writing too many elements in useEffect. This will make our code susceptible to errors:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">function</span> <span class="token function">Post</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token punctuation">{</span> id <span class="token punctuation">,</span> unlisted <span class="token punctuation">}</span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">...</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">fetch</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">/posts/</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> id <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</span> <span class="token punctuation">(</span> <span class="token comment">/* viet code gi do o day */</span> <span class="token punctuation">)</span> <span class="token function">setVisibility</span> <span class="token punctuation">(</span> unlisted <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> id <span class="token punctuation">,</span> unlisted <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">...</span> <span class="token punctuation">}</span> |
In useEffect we’re doing two things, which will result in if the id hasn’t changed then still setVisibility. Instead, it should split into two useEffect:
1 2 3 4 5 6 7 8 | <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 comment">// khi id thay đổi thì fetch bài post</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">/posts/</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> id <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">then</span> <span class="token punctuation">(</span> <span class="token comment">/* ... */</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> id <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 comment">// khi unlisted thay đổi thì update visibility</span> <span class="token function">setVisibility</span> <span class="token punctuation">(</span> unlisted <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> unlisted <span class="token punctuation">]</span> <span class="token punctuation">)</span> |
Ok, so the 7 stinking things are over. Hope this article will help people more in writing code properly and avoid bugs.
If you find the article useful, please do not hesitate to like , share and upvote for yourself.
Many thankssss