1. Mở đầu
Ở bài viết ngày hôm này mình sẽ giới thiệu nốt cho các bạn về Custom Hooks
cũng như một số Hooks
mà các thư viện quen thuộc của React
đã hỗ trợ.
2. React Hook
f. Custom Hook
Ngoài việc sử dụng các Hooks
mà React cung cấp sẵn cho chúng ta như một số mà mình đã giới thiệu trước đó thì React còn cho phép chúng ta tự tạo các Custom Hook
hay bạn có thể hiểu nôm na là các Hooks
riêng do bạn tự tạo. Bên trong các Hooks
tự tạo này bạn hoàn toàn có thể sử dụng luôn các Hook
mà React đã cung cấp như useState
, useReducer
, useEffect
, useMemo
, useCallback
, … . Mục đích của việc tạo Custom Hook
này theo như documents của React nói thì nó sẽ giúp chúng ta:
Building your own Hooks lets you extract component logic into reusable functions.
Hay chính xác là việc hỗ trợ chúng ta trong việc tách phần logic ra thành các Hooks
để có thể tái sử dụng dễ dàng hơn hoặc đơn giản hơn là làm gọn component của chúng ta. Để tạo một Custom Hook
chúng ta sẽ cần tạo một function mới và function này bắt buộc phải bắt đầu bằng từ khóa use giống như tên các Hook
khác của React. Vì nó là một function nên tất nhiên cũng có thể nhận về các tham số mà ta truyền vào và trả về kết quả theo ta muốn. Chúng ta cùng đi đến một ví dụ như sau, nếu các bạn vào Medium và chọn đọc một bài bất kì sẽ thấy được rằng mỗi khi bạn scroll chuột xuống thì phần header của trang web sẽ bị ẩn đi. Ngược lại nếu bạn chỉ scroll chuột lên một cái thì lập tức phần header này sẽ lại được hiển thị ra ngay. Bây giờ chúng ta sẽ cùng thử dựng một cái header có chức năng tương tự như vậy. Code sẽ có dạng như sau:
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 38 | <span class="token keyword">const</span> <span class="token function-variable function">Header</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>style<span class="token punctuation">,</span> setStyle<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 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">const</span> <span class="token function-variable function">handleChangeHeaderStyle</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">if</span> <span class="token punctuation">(</span>document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">getBoundingClientRect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>top <span class="token operator">></span> scrollPos<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Nếu scroll chuột lên</span> <span class="token function">setStyle</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">else</span> <span class="token punctuation">{</span> <span class="token comment">// Nếu scroll chuột xuống</span> <span class="token function">setStyle</span><span class="token punctuation">(</span><span class="token punctuation">{</span> transform<span class="token punctuation">:</span> <span class="token string">"translateY(-100%)"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> scrollPos <span class="token operator">=</span> document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">getBoundingClientRect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>top<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">let</span> scrollPos <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> window<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"scroll"</span><span class="token punctuation">,</span> handleChangeHeaderStyle<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> window<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">"scroll"</span><span class="token punctuation">,</span> handleChangeHeaderStyle<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 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 operator"><</span>div className<span class="token operator">=</span><span class="token string">"App"</span><span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"App__header"</span> style<span class="token operator">=</span><span class="token punctuation">{</span>style<span class="token punctuation">}</span><span class="token operator">></span> <span class="token constant">HEADER</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"App__seperator"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"App__body"</span><span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span><span class="token constant">TITLE</span><span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span> <span class="token constant">SOME</span> <span class="token constant">LONG</span> <span class="token constant">CONTENT</span> <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>div<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><span class="token punctuation">;</span> |
ở đây mình áp dụng luôn các Hook
đã trình bày ở các bài trước đó là useState
và useEffect
. Về cơ bản đoạn code trên các bạn có thể hiểu ý tưởng ở đây là:
- Khi ta scroll chuột xuống thì sẽ dùng style để ẩn phần header đi bằng cách cho nó
translateY(-100%)
còn ngược lại sẽ cho nó hiển thị như ban đầu - Phần
style
này ta sẽ chưa trong một local state bằng cách dùnguseState
- Tiếp đó ta sử dụng
useEffect
để dùng để lăng nghe sự kiện scroll chuột trong trang và thay đổistyle
sao cho phù hợp với sự kiện
Kết quả bạn có thể xem ở đây: https://codesandbox.io/s/usescrollhook-tceov
Với đoạn code trên mọi thứ đều ngon lành vì chúng ta đạt được mục tiêu mong muốn. Tuy nhiên, trong trường hợp web của bạn có thêm bản responsive cho riêng mobile và tất nhiên cũng cần tình năng nói trên thì chúng ta xử lý ra sao ? Tất nhiên ta cũng có thể đơn giản là copy cái đoạn code kia và paste lại qua file component của phần header cho mobile sử dụng và thường thì chả có vấn đề gì ở đây cả . Tuy nhiên vì đây là ví dụ nên giả sau sau này đoạn code trên được thay đổi và có thêm nhiều sự chỉnh sửa về style hơn là chỉ translateY(-100%)
thì lúc này khi sửa bạn sẽ phải nhớ sửa cả hai file. Hoặc ngay từ đầu ta có thể tạo ra một Hooks
dùng chung cho cả bản mobile và bản desktop thì sẽ hay hơn. Để làm được điều này rất đơn giản, ta sẽ tạo một file mới như sau:
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">import</span> <span class="token punctuation">{</span> useState<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">useScollHook</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>style<span class="token punctuation">,</span> setStyle<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 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">const</span> <span class="token function-variable function">handleChangeHeaderStyle</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">if</span> <span class="token punctuation">(</span>document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">getBoundingClientRect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>top <span class="token operator">></span> scrollPos<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">setStyle</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">else</span> <span class="token punctuation">{</span> <span class="token function">setStyle</span><span class="token punctuation">(</span><span class="token punctuation">{</span> transform<span class="token punctuation">:</span> <span class="token string">"translateY(-100%)"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> scrollPos <span class="token operator">=</span> document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">getBoundingClientRect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>top<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">let</span> scrollPos <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> window<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"scroll"</span><span class="token punctuation">,</span> handleChangeHeaderStyle<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> window<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">"scroll"</span><span class="token punctuation">,</span> handleChangeHeaderStyle<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 punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> style<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Như mình đã nói ban đầu các Custom Hook
mà bạn tạo ra bắt buộc phải có tên bắt đầu bằng từ khóa use. Như bạn có thể thấy đây đơn giản chỉ là một function useScrollHook
, nó không nhận vào tham số gì cả và kết quả trả về ở đây là một object có tên là style
. Ở đây mình đã copy toàn bộ phần logic liên quan đến việc thay đổi style header bao gồm phần useState
và useEffect
ở component ban đầu và cho vào trong function mới này. Lúc này trong component Header
ta chỉ cần viết lại như sau:
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">import</span> useScrollHook <span class="token keyword">from</span> <span class="token string">'./useScrollHook'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">Header</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> style <span class="token operator">=</span> <span class="token function">useScrollHook</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 operator"><</span>div className<span class="token operator">=</span><span class="token string">"App"</span><span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"App__header"</span> style<span class="token operator">=</span><span class="token punctuation">{</span>style<span class="token punctuation">}</span><span class="token operator">></span> <span class="token constant">HEADER</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"App__seperator"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"App__body"</span><span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span><span class="token constant">TITLE</span><span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span> <span class="token constant">SOME</span> <span class="token constant">LONG</span> <span class="token constant">CONTENT</span> <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>div<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><span class="token punctuation">;</span> |
Như bạn có thể thấy code của bạn đã gọn hơn rất nhiều so với ban đầu và đồng thời ở component cho header của mobile bạn cũng chỉ cần import lại Hook
vừa tạo ra và sử dụng như trên. Trên thực tế trong dự án mình cũng hay sử dụng Custom Hook
khá nhiều vì mình muốn thử sử dụng công nghệ mới của React xem nó ra làm sao . Với cá nhân thì mình thấy việc sử dụng Custom Hook
mang lại cho bản thân mình một số lợi ích như:
- Phân tách riêng được phần logic ra file riêng để làm gọn cho component chính. Component của bạn lúc này cũng chỉ chứa đa phần code liên quan đến UI.
- Trong trường hợp chỉ cần sửa style thì cho component đó thì bạn cũng sẽ không mất công scroll chuột quá nhiều vì logic không còn nằm ở chỗ này nữa mà chỉ có riêng phần UI.
- Trường hợp bạn cần sửa một phần logic riêng biệt ví dụ như chức năng scroll chuột nói trên thì bạn chỉ cần mở
Hook
phục vụ riêng cho phần logic đó ra thay vì phải lăn chuột đi tìm cái hàm phụ trách việc này
Tất nhiên như mình nói ở trên Custom Hook
của bạn có thể nhận vào tham số bất kì và sử dụng nó:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">const</span> <span class="token function-variable function">useDemoHook</span> <span class="token operator">=</span> <span class="token punctuation">(</span>param1<span class="token punctuation">,</span> param2<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// Do anything you want</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">DemoComponent</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> result <span class="token operator">=</span> <span class="token function">useDemoHook</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">,</span> <span class="token string">'Hi'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Hoặc cũng có thể trả ra nhiều thứ hơn là chỉ một biến kết quả ta cũng có thể trả ra nhiều kết quả và thậm chỉ trả về cả một function như sau:
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 | <span class="token keyword">const</span> <span class="token function-variable function">useLoginHook</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>formData<span class="token punctuation">,</span> setFormData<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>email<span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">,</span> password<span class="token punctuation">:</span> <span class="token string">''</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">handleInputChange</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Handle change email or password input</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">handleLogin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Handle login</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">[</span> formData<span class="token punctuation">,</span> handleInputChange<span class="token punctuation">,</span> handleLogin <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">DemoComponent</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>formData<span class="token punctuation">,</span> handleInputChange<span class="token punctuation">,</span> handleLogin<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useLoginHook</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 operator"><</span>div className<span class="token operator">=</span><span class="token string">"form"</span><span class="token operator">></span> <span class="token operator"><</span>input name<span class="token operator">=</span><span class="token string">"email"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>formData<span class="token punctuation">.</span>email<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span>handleInputChange<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>input name<span class="token operator">=</span><span class="token string">"password"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>formData<span class="token punctuation">.</span>password<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span>handleInputChange<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>handleLogin<span class="token punctuation">}</span><span class="token operator">></span><span class="token constant">LOGIN</span><span class="token operator"><</span><span class="token operator">/</span>button<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> |
Như bạn thấy với ví dụ trên thì thay vì ta phải viết rất nhiều logic liên quan đến việc login vào trong component đó như:
- Thay đổi nội dung input
- Validate nội dung nhập có hợp lệ không
- Gửi dữ liệu lên server để login
Thì giờ đây với việc tách ra thành Custom Hooks
thì component của chúng ta lúc này chỉ nhận vào những gì nó cần và component trở nên gọn gàng hơn rất nhiều.
3. Hook trong các thư viện phổ biến khác
a. React Redux
Với tính Hook
mà React cung cấp thì react-redux
cũng đã hỗ trợ chúng ta sử dụng Hooks
với ba Hook
lần lượt là:
useSelector()
: Cho phép bạn lấy dữ liệu từ store của redux – đóng vai trò giống nhưmapStateToProps
trong hàmconnect()
mà chúng ta hay dùng trước kia. Chi tiết: https://react-redux.js.org/api/hooks#useselectoruseDispatch()
: Cho phép chúng ta dispatch 1 action đến redux – đóng vai trò giống nhưmapDispatchToProps
trong hàmconnect()
mà chúng ta dùng trước kia. Chi tiết: https://react-redux.js.org/api/hooks#usedispatchuseStore()
: Cho phép chúng ta truy cập trực tiếp đến object store trong redux và gọi đến các hàm nhưstore.getState()
, … . Chi tiết: https://react-redux.js.org/api/hooks#usestore
Ví dụ sử dụng useSelector()
và connect()
:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token comment">// connect()</span> <span class="token keyword">const</span> <span class="token function-variable function">mapStateToProps</span> <span class="token operator">=</span> state <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> posts<span class="token punctuation">:</span> state<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> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token function">connect</span><span class="token punctuation">(</span>mapStateToProps<span class="token punctuation">)</span><span class="token punctuation">(</span>SomeComponent<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// useSelector</span> <span class="token keyword">const</span> <span class="token function-variable function">SomeComponent</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> posts <span class="token operator">=</span> <span class="token function">useSelector</span><span class="token punctuation">(</span>state <span class="token operator">=></span> state<span class="token punctuation">.</span>posts<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Như bạn đã thấy kết quả ở đây ta thu được tương tự nhau và kết quả cũng tương đương nếu bạn sử dụng useDispatch()
.
b. React Router
Nếu như trước kia để truy cập được những thông tin liên quan đến router thì việc chúng ta cần làm đó là bọc component của chúng ta vào component withRouter
. Tuy nhiên ở phiên bản mới nhất thì React Router
đã cho phép chúng ta truy cập vào các thông tin liên quan đến router thông qua một số Hook
như sau:
useHistory
: cho phép chúng ta truy cập vào objecthistory
để có thể thực hiện các thao tác liên quan đến thay đổi url, ví dụ từ documents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">import</span> <span class="token punctuation">{</span> useHistory <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react-router-dom"</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">HomeButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> history <span class="token operator">=</span> <span class="token function">useHistory</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">handleClick</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> history<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">"/home"</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 operator"><</span>button type<span class="token operator">=</span><span class="token string">"button"</span> onClick<span class="token operator">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span><span class="token operator">></span> Go home <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
useLocation
: nếu đơn giản bạn chỉ cần đến nội dung trong url hiện tại trong objectlocation
thì đây chính là hook bạn cần thay vì lấy toàn bộ từwithRouter
. ví dụ từ documents:
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 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">"react-dom"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> BrowserRouter <span class="token keyword">as</span> Router<span class="token punctuation">,</span> Switch<span class="token punctuation">,</span> useLocation <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react-router-dom"</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">usePageViews</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> location <span class="token operator">=</span> <span class="token function">useLocation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> React<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> ga<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">"pageview"</span><span class="token punctuation">,</span> location<span class="token punctuation">.</span>pathname<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>location<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">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">usePageViews</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 operator"><</span>Switch<span class="token operator">></span><span class="token operator">...</span><span class="token operator"><</span><span class="token operator">/</span>Switch<span class="token operator">></span><span class="token punctuation">;</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>Router<span class="token operator">></span> <span class="token operator"><</span>App <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Router<span class="token operator">></span><span class="token punctuation">,</span> node <span class="token punctuation">)</span><span class="token punctuation">;</span> |
useParams
: trường hợp router của bạn nhận vào các tham số và bạn muốn sử dụng lại nó trong component thì hay sử dụng hooks này. Ví dụ:
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 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">"react-dom"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> BrowserRouter <span class="token keyword">as</span> Router<span class="token punctuation">,</span> Switch<span class="token punctuation">,</span> Route<span class="token punctuation">,</span> useParams <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react-router-dom"</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">BlogPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> <span class="token punctuation">{</span> slug <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useParams</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 operator"><</span>div<span class="token operator">></span>Now showing post <span class="token punctuation">{</span>slug<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> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>Router<span class="token operator">></span> <span class="token operator"><</span>Switch<span class="token operator">></span> <span class="token operator"><</span>Route exact path<span class="token operator">=</span><span class="token string">"/"</span><span class="token operator">></span> <span class="token operator"><</span>HomePage <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Route<span class="token operator">></span> <span class="token operator"><</span>Route path<span class="token operator">=</span><span class="token string">"/blog/:slug"</span><span class="token operator">></span> <span class="token operator"><</span>BlogPost <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Route<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Switch<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Router<span class="token operator">></span><span class="token punctuation">,</span> node <span class="token punctuation">)</span><span class="token punctuation">;</span> |
4. Kết bài
Chuỗi bài viết liên quan đến Hook
trong React của mình đến đây là kết thúc. Nếu các bạn có điều gì thắc mắc hoặc tìm thấy mình sai ở điểm nào hãy bình luận ngay phía dưới để mình biết. Cảm ơn các bạn đã đọc bài và đừng quên để lại 1 upvote