Bài viết được dịch từ bài viết How I Eliminated Redux Boilerplate with Hooks-for-Redux
Redux rất là tuyệt vời. Nó giúp bạn quản lý, kiểm tra state của ứng dụng một cách dễ dàng nhất. Hơn nữa, có rất nhiều thư viện hỗ trợ để bạn nghịch redux như là: react-redux, redux-devtools, redux-logger.
Tuy nhiên Redux lại có một điểm trừ, đó là phải tốn quá nhiều thời gian để viết redux theo một mẫu tiêu chuẩn. Mà đáng ra điều này phải được làm tự động.
Sau khi tham gia một số dự án sử dụng Redux và nhận thấy các kiểu mẫu này, tôi bắt đầu thiết kế một công cụ để tự động hóa nó. Điều này đã được nhiều người nhận thấy trước đó rồi: reduce-react-boilerplate, reducing-boilerplate-in-redux, minimize-redux-boilerplate-in-4-lines-of-code, cũng như là giải quyết vấn đề này: reduxless, redux-actions, redux-arc và hơn thế nữa. Tuy nhiên những cách trước đó đều thất bại vì một trong hai lý do sau:
- Tạo ra một giải pháp không tích hợp được hệ thống Redux.
- Không loại bỏ được sự dư thừa của mẫu tiêu chuẩn Redux.
Vậy là tôi đã tạo ra hooks-for-redux. Tôi thích cái cách mà Hooks làm cho React gọn gàng hơn, nên tôi đã tạo ra một Api tương tự để làm gọn Redux. Sau đây là ví dụ về cách mà H4R hoạt động:
Cách tôi dùng H4R để loại bỏ 52% mã trong ứng dụng React-Hook-Todo
Gần đây tôi có đọc được một bài viết tuyệt vời của Sunil Sandhu, kể chi tiết cách Hooks làm gọn Redux trong Components. Tôi sẽ dùng kết quả của anh ấy làm khởi đầu:
- how-i-reduced-my-redux-code-using-redux-hooks
- all 177 lines of JavaScript from Sunil’s code in one file
Cho những ai lười, bạn có thể thấy được kết quả ở đây:
Logic cơ bản của ứng dụng To-Do
Trước khi đi vào code, sẽ tốt hơn nếu hiểu được logic của ứng dụng. Bắt đầu với giao diện người dùng, chúng ta sẽ có một mã giả cho React component như thế này:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">const</span> <span class="token function-variable function">ToDoItem</span> <span class="token operator">=</span> <span class="token punctuation">(</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 operator"><</span>li<span class="token operator">></span> <span class="token punctuation">{</span>item<span class="token punctuation">.</span>text<span class="token punctuation">}</span> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>deleteItem<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>li<span class="token operator">></span> <span class="token keyword">const</span> <span class="token function-variable function">ToDo</span> <span class="token operator">=</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 operator"><</span>ul<span class="token operator">></span> <span class="token punctuation">{</span><span class="token function">useList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>item <span class="token operator">=></span> <span class="token punctuation">(</span> <span class="token operator"><</span>ToDoItem key<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id<span class="token punctuation">}</span> item<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></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>ul<span class="token operator">></span> <span class="token operator"><</span>input 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 operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>addItem<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>div<span class="token operator">></span> |
Như bạn thấy, chỉ có hai thành phần. ToDo bao gồm:
- Một danh sách các ToDoItem lấy từ useList. Mỗi Item chứa:
- Văn bản hiển thị.
- Một nút để xóa phần tử.
- Một input để thêm một ToDo mới
Mã giả này gần như có đủ chức năng, ngoại trừ hàm addItem và hàm deleteItem được truyền vào như tham số
Phần còn lại của ứng dụng là quản lý danh sách việc cần làm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">let</span> list <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> text<span class="token punctuation">:</span> <span class="token string">"clean the house"</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 number">2</span><span class="token punctuation">,</span> text<span class="token punctuation">:</span> <span class="token string">"buy milk"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// REDUCERS</span> <span class="token keyword">const</span> <span class="token function-variable function">_addItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span>list<span class="token punctuation">,</span> item<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token operator">...</span>list<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>item<span class="token punctuation">,</span> id<span class="token punctuation">:</span> <span class="token function">uniqueId</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 function-variable function">_deleteItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span>list<span class="token punctuation">,</span> item<span class="token punctuation">)</span> <span class="token operator">=></span> list<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>todo <span class="token operator">=></span> todo<span class="token punctuation">.</span>id <span class="token operator">!==</span> item<span class="token punctuation">.</span>id<span class="token punctuation">)</span> <span class="token comment">// STUBS</span> <span class="token keyword">const</span> <span class="token function-variable function">useList</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> list <span class="token comment">// react hook</span> <span class="token keyword">const</span> <span class="token function-variable function">deleteItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span>item<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">null</span> <span class="token comment">// dispatcher</span> <span class="token keyword">const</span> <span class="token function-variable function">addItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span>item<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">null</span> <span class="token comment">//dispatcher</span> |
Ở phần đầu, chúng ta có cấu trúc của danh sách, và state khởi tạo ban đầu.
Tiếp theo là mô tả 2 chức năng: thêm và xóa phần tử. Lấy danh sách hiện tại, thực hiện thêm và trả về một danh sách mới.
Cuối cùng có ba mô tả sơ khai cho các chức năng trên:
- useList trả về giá trị danh sách hiện tại.
- deleteItem xóa phần tử khỏi danh sách
- addItem thêm phần tử vào danh sách
Toàn bộ logic cần thiết của ứng dụng ToDo chỉ tốn khoảng 30 dòng code. Một ứng dụng thực tế sẽ tốn nhiều hơn, nhưng mục tiêu ở đây là càng ít càng tốt.
Bắt đầu nào
Bắt đầu với file gốc index.js
. Tôi sẽ cho bạn thấy trước và sau và giải thích sự thay đổi.
Tôi sử dụng số dòng để đo kích thước code. Mặc dù nó không phải là phương pháp tốt, nhưng nó đơn giản. Thêm về suy nghĩ về việc đếm code trong tokens
src/index.js (22% gọn hơn)
Ban đầu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">import</span> React form <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> Provider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react-redux"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> configureStore <span class="token keyword">from</span> <span class="token string">"./redux/store/configureStore"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> App <span class="token keyword">from</span> <span class="token string">"./App"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">configureStore</span><span class="token punctuation">(</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>Provider store<span class="token operator">=</span><span class="token punctuation">{</span>store<span class="token punctuation">}</span><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>Provider<span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"root"</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> |
Sau đó
1 2 3 4 5 6 7 8 9 10 11 12 | <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> Provider <span class="token punctuation">}</span> <span class="token keyword">from</span> 'react<span class="token operator">-</span>redux"<span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> App <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./App"</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>Provider<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>Provider<span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"root"</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> |
Bạn sẽ nhận thấy được 2 thay đổi ở đây. Đầu tiên không có lệnh gọi configureStore
và thứ hai là Provider
không yêu cầu tham số store
. Hook-for-redux được thiết kế để thêm các reducer
vào đang tồn tại thay vì yêu cầu tất cả các reducer
khi khởi tạo store
. Điều này cho phép chúng ta sử dụng store
mặc định. Bạn vẫn có thể ghi đè store
mặc định nếu cần.
src/App.js (67% gọn hơn)
Ban đầu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <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> <span class="token punctuation">{</span> useSelector<span class="token punctuation">,</span> useDispatch <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react-redux"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> appActions <span class="token keyword">from</span> <span class="token string">"./redux/actions/appActions"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> ToDo <span class="token keyword">from</span> <span class="token string">"./components/ToDo"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token string">"./App.css"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">App</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> list <span class="token operator">=</span> <span class="token function">useSelector</span><span class="token punctuation">(</span><span class="token punctuation">(</span>store<span class="token punctuation">)</span> <span class="token operator">=></span> store<span class="token punctuation">.</span>appReducer<span class="token punctuation">.</span>list<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> dispatch <span class="token operator">=</span> <span class="token function">useDispatch</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">redux_add</span> <span class="token operator">=</span> <span class="token punctuation">(</span>todo<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">dispatch</span><span class="token punctuation">(</span>appActions<span class="token punctuation">.</span><span class="token function">redux_add</span><span class="token punctuation">(</span>todo<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">redux_delete</span> <span class="token operator">=</span> <span class="token punctuation">(</span>id<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">dispatch</span><span class="token punctuation">(</span>appActions<span class="token punctuation">.</span><span class="token function">redux_delete</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> props <span class="token operator">=</span> <span class="token punctuation">{</span> list<span class="token punctuation">,</span> redux_add<span class="token punctuation">,</span> redux_delete <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token operator"><</span>ToDo <span class="token punctuation">{</span><span class="token operator">...</span>props<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></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> App<span class="token punctuation">;</span> |
Sau đó
1 2 3 4 5 6 | <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> <span class="token punctuation">{</span> ToDo <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./components/ToDo"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token string">"./App.css"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">App</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token operator"><</span>ToDo <span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">;</span> |
Đơn giản hóa App.js
khá đơn giản. App.js
không nên phụ thuộc và trạng thái danh sách. Điều này sẽ gây nên một số vấn đề về việc re-render.
src/components/ToDo.js (42% gọn hơn)
ToDo là thành phần chính trình bày todo-list. Đây là file lớn và có nhiều thay đổi nhất. Đa phần là cải tiến nhỏ trong cách sử dụng React. Mục tiêu là giảm mã mà không mất đi sự rành mạch.
Ban đầu:
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <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">import</span> ReduxLogo <span class="token keyword">from</span> <span class="token string">"../assets/redux.png"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> ToDoItem <span class="token keyword">from</span> <span class="token string">"./ToDoItem"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token string">"./ToDo.css"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">ToDo</span> <span class="token operator">=</span> props <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> list<span class="token punctuation">,</span> redux_add<span class="token punctuation">,</span> redux_delete <span class="token punctuation">}</span> <span class="token operator">=</span> props<span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>todo<span class="token punctuation">,</span> setTodo<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 punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">generateId</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>list <span class="token operator">&&</span> list<span class="token punctuation">.</span>length <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">return</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token operator">...</span>list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>t <span class="token operator">=></span> t<span class="token punctuation">.</span>id<span class="token punctuation">)</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">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token number">1</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 function-variable function">createNewToDoItem</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 comment">//validate todo</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>todo<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"Please enter a todo!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> newId <span class="token operator">=</span> <span class="token function">generateId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">redux_add</span><span class="token punctuation">(</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> newId<span class="token punctuation">,</span> text<span class="token punctuation">:</span> todo <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">setTodo</span><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 punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">handleKeyPress</span> <span class="token operator">=</span> e <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>key <span class="token operator">===</span> <span class="token string">"Enter"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">createNewToDoItem</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">const</span> <span class="token function-variable function">handleInput</span> <span class="token operator">=</span> e <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">setTodo</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<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">deleteItem</span> <span class="token operator">=</span> todo <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">redux_delete</span><span class="token punctuation">(</span>todo<span class="token punctuation">.</span>id<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">"ToDo"</span><span class="token operator">></span> <span class="token operator"><</span>img className<span class="token operator">=</span><span class="token string">"Logo"</span> src<span class="token operator">=</span><span class="token punctuation">{</span>ReduxLogo<span class="token punctuation">}</span> alt<span class="token operator">=</span><span class="token string">"logo"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"ToDo-Header"</span><span class="token operator">></span>Redux To Do<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"ToDo-Container"</span><span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"ToDo-Content"</span><span class="token operator">></span> <span class="token punctuation">{</span>list <span class="token operator">&&</span> list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>item <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>ToDoItem key<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id<span class="token punctuation">}</span> item<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">}</span> deleteItem<span class="token operator">=</span><span class="token punctuation">{</span>deleteItem<span class="token punctuation">}</span> <span class="token operator">/</span><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><span class="token punctuation">}</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">"ToDoInput"</span><span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>todo<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span>handleInput<span class="token punctuation">}</span> onKeyPress<span class="token operator">=</span><span class="token punctuation">{</span>handleKeyPress<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>button className<span class="token operator">=</span><span class="token string">"ToDo-Add"</span> onClick<span class="token operator">=</span><span class="token punctuation">{</span>createNewToDoItem<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>button<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 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> <span class="token keyword">export</span> <span class="token keyword">default</span> ToDo<span class="token punctuation">;</span> |
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 39 40 41 42 43 | <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <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">import</span> ReduxLogo <span class="token keyword">from</span> <span class="token string">"../assets/redux.png"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> ToDoItem <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./ToDoItem"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token string">"./ToDo.css"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> addItem<span class="token punctuation">,</span> useList <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"../redux/list"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">ToDo</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> list <span class="token operator">=</span> <span class="token function">useList</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>text<span class="token punctuation">,</span> setText<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 punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">createNewToDoItem</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><span class="token operator">!</span>text<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"Please enter a text!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">addItem</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 punctuation">;</span> <span class="token function">setText</span><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 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">"ToDo"</span><span class="token operator">></span> <span class="token operator"><</span>img className<span class="token operator">=</span><span class="token string">"Logo"</span> src<span class="token operator">=</span><span class="token punctuation">{</span>ReduxLogo<span class="token punctuation">}</span> alt<span class="token operator">=</span><span class="token string">"logo"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"ToDo-Header"</span><span class="token operator">></span>Redux To Do<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"ToDo-Container"</span><span class="token operator">></span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"ToDo-Content"</span><span class="token operator">></span> <span class="token punctuation">{</span>list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>item <span class="token operator">=></span> <span class="token punctuation">(</span> <span class="token operator"><</span>ToDoItem key<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id<span class="token punctuation">}</span> item<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></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 operator"><</span>div className<span class="token operator">=</span><span class="token string">"ToDoInput"</span><span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>text<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span>e <span class="token operator">=></span> <span class="token function">setText</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span> onKeyPress<span class="token operator">=</span><span class="token punctuation">{</span>e <span class="token operator">=></span> e<span class="token punctuation">.</span>key <span class="token operator">===</span> <span class="token string">"Enter"</span> <span class="token operator">&&</span> <span class="token function">createNewToDoItem</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> <span class="token operator"><</span>button className<span class="token operator">=</span><span class="token string">"ToDo-Add"</span> onClick<span class="token operator">=</span><span class="token punctuation">{</span>createNewToDoItem<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>button<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 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> |
Làm gọn mã React:
- Tôi sử dụng
export-const
thay vìexport-default
. Một số vấn đề vớiexport-default
là khi nhập mặc định, bạn có thể gán bất cứ tên nào bạn muốn và điều đó tạo nên sự không nhất quán trong dự án. Tuy nhiên vấn đề lớn nhất củaexport-default
là nó không hoạt động vớiimport *
hayexport *
– đây là một cấu trúc tốt để giảm mã. - Giảm bớt định nghĩa hàm cho những hành động chỉ sử dụng một lần.
Và những thay đổ đáng kể nữa:
- Import trực tiếp
addItem
vàuseList
. Chúng không nên được truyền vào như là mộtprops
- Loại bỏ
generateId
. Đây không phải là trách nhiệm của component ToDo. - Loại bỏ
deleteItem
.ToDo.js
không bao giờ sử dụng chúng.
src/components/ToDoItem.js (35% gọn hơn)
Ban đầu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <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> <span class="token string">"./ToDoItem.css"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">ToDoItem</span> <span class="token operator">=</span> props <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> item<span class="token punctuation">,</span> deleteItem <span class="token punctuation">}</span> <span class="token operator">=</span> props<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">"ToDoItem"</span><span class="token operator">></span> <span class="token operator"><</span>p className<span class="token operator">=</span><span class="token string">"ToDoItem-Text"</span><span class="token operator">></span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>text<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span>button className<span class="token operator">=</span><span class="token string">"ToDoItem-Delete"</span> onClick<span class="token operator">=</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">deleteItem</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 operator">-</span> <span class="token operator"><</span><span class="token operator">/</span>button<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> <span class="token keyword">export</span> <span class="token keyword">default</span> ToDoItem<span class="token punctuation">;</span> |
Sau đó
1 2 3 4 5 6 7 8 9 10 11 12 | <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> <span class="token string">"./ToDoItem.css"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> deleteItem <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"../redux/list"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">ToDoItem</span> <span class="token operator">=</span> <span class="token punctuation">(</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 operator"><</span>div className<span class="token operator">=</span><span class="token string">"ToDoItem"</span><span class="token operator">></span> <span class="token operator"><</span>p className<span class="token operator">=</span><span class="token string">"ToDoItem-Text"</span><span class="token operator">></span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>text<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span>button className<span class="token operator">=</span><span class="token string">"ToDoItem-Delete"</span> onClick<span class="token operator">=</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">deleteItem</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 operator">-</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> |
deleteItem
import trực tiếp thay vì nhận từ propsexport-const
giống vớiToDo.js
- phân mảnh
props
và return trực tiếp
redux/list.js (74% dòng rút gọn, 80% file rút gọn)
Bây giờ mới là ma thuật thật sự. H4R useRedux loại bỏ tất cả bản mẫu để quản lý redux store
của bạn, và nó không làm mất đi tính tương thích ban đầu. Đặt tất cả redux logic vào trong 1 file.
Lưu ý, trong dự án lớn hơn, tôi khuyên bạn nên tạo một tệp cho mỗi model dữ liệu. Tuy nhiên, trong ứng dụng đơn giản này, chỉ cần có duy nhất một model: danh sách todo.
Ban đầu (5 file – 61 dòng)
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | <span class="token comment">//**********************************************</span> <span class="token comment">// src/redux/actions/appActions.js</span> <span class="token comment">//**********************************************</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token constant">ADD_ITEM</span><span class="token punctuation">,</span> <span class="token constant">DELETE_ITEM</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"../actionTypes"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">redux_add</span> <span class="token operator">=</span> todo <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token constant">ADD_ITEM</span><span class="token punctuation">,</span> payload<span class="token punctuation">:</span> todo <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">redux_delete</span> <span class="token operator">=</span> id <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token constant">DELETE_ITEM</span><span class="token punctuation">,</span> payload<span class="token punctuation">:</span> id <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> appActions <span class="token operator">=</span> <span class="token punctuation">{</span> redux_add<span class="token punctuation">,</span> redux_delete <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> appActions<span class="token punctuation">;</span> <span class="token comment">//**********************************************</span> <span class="token comment">// src/redux/actionTypes/index.js</span> <span class="token comment">//**********************************************</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">ADD_ITEM</span> <span class="token operator">=</span> <span class="token string">"ADD_ITEM"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">DELETE_ITEM</span> <span class="token operator">=</span> <span class="token string">"DELETE_ITEM"</span><span class="token punctuation">;</span> <span class="token comment">//**********************************************</span> <span class="token comment">// src/redux/reducers/appReducer.js</span> <span class="token comment">//**********************************************</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token constant">ADD_ITEM</span><span class="token punctuation">,</span> <span class="token constant">DELETE_ITEM</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"../actionTypes"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token punctuation">{</span> list<span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> text<span class="token punctuation">:</span> <span class="token string">"clean the house"</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 number">2</span><span class="token punctuation">,</span> text<span class="token punctuation">:</span> <span class="token string">"buy milk"</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">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">appReducer</span><span class="token punctuation">(</span>state <span class="token operator">=</span> initialState<span class="token punctuation">,</span> action<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 constant">ADD_ITEM</span><span class="token punctuation">:</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> list<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>state<span class="token punctuation">.</span>list<span class="token punctuation">,</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">return</span> state<span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token constant">DELETE_ITEM</span><span class="token punctuation">:</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> list<span class="token punctuation">:</span> state<span class="token punctuation">.</span>list<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>todo <span class="token operator">=></span> todo<span class="token punctuation">.</span>id <span class="token operator">!==</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">return</span> state<span class="token punctuation">;</span> <span class="token keyword">default</span><span class="token punctuation">:</span> <span class="token keyword">return</span> state<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//**********************************************</span> <span class="token comment">// src/redux/reducers/index.js</span> <span class="token comment">//**********************************************</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> combineReducers <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"redux"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> appReducer <span class="token keyword">from</span> <span class="token string">"./appReducer"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> rootReducer <span class="token operator">=</span> <span class="token function">combineReducers</span><span class="token punctuation">(</span><span class="token punctuation">{</span> appReducer <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> rootReducer<span class="token punctuation">;</span> <span class="token comment">//**********************************************</span> <span class="token comment">// src/redux/store/configureStore.js</span> <span class="token comment">//**********************************************</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"redux"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> rootReducer <span class="token keyword">from</span> <span class="token string">"../reducers"</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">configureStore</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 function">createStore</span><span class="token punctuation">(</span>rootReducer<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Sau đó (1 file – 16 dòng)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">import</span> <span class="token punctuation">{</span> useRedux <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"hooks-for-redux"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">getUniqueId</span> <span class="token operator">=</span> list <span class="token operator">=></span> list<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">?</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token operator">...</span>list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>t <span class="token operator">=></span> t<span class="token punctuation">.</span>id<span class="token punctuation">)</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 number">1</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>useList<span class="token punctuation">,</span> <span class="token punctuation">{</span> addItem<span class="token punctuation">,</span> deleteItem <span class="token punctuation">}</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useRedux</span><span class="token punctuation">(</span> <span class="token string">"list"</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 number">1</span><span class="token punctuation">,</span> text<span class="token punctuation">:</span> <span class="token string">"clean the house"</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 number">2</span><span class="token punctuation">,</span> text<span class="token punctuation">:</span> <span class="token string">"buy milk"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> addItem<span class="token punctuation">:</span> <span class="token punctuation">(</span>list<span class="token punctuation">,</span> item<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token operator">...</span>list<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>item<span class="token punctuation">,</span> id<span class="token punctuation">:</span> <span class="token function">getUniqueId</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> deleteItem<span class="token punctuation">:</span> <span class="token punctuation">(</span>list<span class="token punctuation">,</span> item<span class="token punctuation">)</span> <span class="token operator">=></span> list<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>todo <span class="token operator">=></span> todo<span class="token punctuation">.</span>id <span class="token operator">!==</span> item<span class="token punctuation">.</span>id<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> |
getUniqueId
cơ bản giống như generatedId
ban đầu ở ToDo.js
. Phần còn lại là lệnh gọi useRedux. Gồm có 3 đối số:
storeKey
tên của state được lưu trongredux store
- state khởi tạo
reducer
Và nó có trả về:
- Một hook để lấy state hiện tại và re-render lại mỗi khi state thay đổi
- Một đối tượng chứa các dispatchers tương ứng với reducer
Đây là cách hooks-for-redux thực thi. Nó lấy thông tin cần thiết để định nghĩa state của bạn – tên, state khởi tạo và reducer và nó trả về các phương thức cần thiết để tương tác với state đó.
Cuối cùng! Chúng ta đã làm như thế nào?
Mã nguồn ban đầu là 177 dòng code. Với hooks-for-redux, nó được tối giản xuoons còn 85 dòng. Chỉ 48% số dòng và từ 9 file xuống còn 5. Bạn có thể hợp nhất tất cả vào cùng một file, và loại bỏ được các dòng import
và export
và nếu loại bỏ cả style
thì nó có thể giảm xuống còn 45 dòng.
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 39 40 41 42 43 44 45 | <span class="token comment">// working, though styleless, essential H4R ToDo app</span> <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <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">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> useRedux<span class="token punctuation">,</span> Provider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"hooks-for-redux"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">getUniqueId</span> <span class="token operator">=</span> list <span class="token operator">=></span> list<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">?</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token operator">...</span>list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>t <span class="token operator">=></span> t<span class="token punctuation">.</span>id<span class="token punctuation">)</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 number">1</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>useList<span class="token punctuation">,</span> <span class="token punctuation">{</span> addItem<span class="token punctuation">,</span> deleteItem <span class="token punctuation">}</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useRedux</span><span class="token punctuation">(</span><span class="token string">"list"</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> addItem<span class="token punctuation">:</span> <span class="token punctuation">(</span>list<span class="token punctuation">,</span> item<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token operator">...</span>list<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>item<span class="token punctuation">,</span> id<span class="token punctuation">:</span> <span class="token function">getUniqueId</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> deleteItem<span class="token punctuation">:</span> <span class="token punctuation">(</span>list<span class="token punctuation">,</span> item<span class="token punctuation">)</span> <span class="token operator">=></span> list<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>todo <span class="token operator">=></span> todo<span class="token punctuation">.</span>id <span class="token operator">!==</span> item<span class="token punctuation">.</span>id<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">ToDoItem</span> <span class="token operator">=</span> <span class="token punctuation">(</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 operator"><</span>li<span class="token operator">></span> <span class="token punctuation">{</span>item<span class="token punctuation">.</span>text<span class="token punctuation">}</span> <span class="token operator"><</span>button onClick<span class="token operator">=</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">deleteItem</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><span class="token string">" - "</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span> <span class="token keyword">const</span> <span class="token function-variable function">ToDo</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>text<span class="token punctuation">,</span> setText<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 punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">createNewToDoItem</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><span class="token operator">!</span>text<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"Please enter a text!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">addItem</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 punctuation">;</span> <span class="token function">setText</span><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 punctuation">;</span> <span class="token keyword">return</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 punctuation">{</span><span class="token function">useList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>item <span class="token operator">=></span> <span class="token operator"><</span>ToDoItem key<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id<span class="token punctuation">}</span> item<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>text<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span>e <span class="token operator">=></span> <span class="token function">setText</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span> onKeyPress<span class="token operator">=</span><span class="token punctuation">{</span>e <span class="token operator">=></span> e<span class="token punctuation">.</span>key <span class="token operator">===</span> <span class="token string">"Enter"</span> <span class="token operator">&&</span> <span class="token function">createNewToDoItem</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> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>createNewToDoItem<span class="token punctuation">}</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token string">" + "</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>button<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> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token operator"><</span>Provider<span class="token operator">></span><span class="token operator"><</span>ToDo <span class="token operator">/</span><span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>Provider<span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"root"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |