{"id":1155,"date":"2022-02-26T01:52:23","date_gmt":"2022-02-26T01:52:23","guid":{"rendered":"https:\/\/egany.com\/blogs\/?p=1155"},"modified":"2022-02-26T08:49:43","modified_gmt":"2022-02-26T08:49:43","slug":"frontend-du-ky-s2e3-cross-platform-apps-phan-3-co-cong-mai-sat-co-ngay-release","status":"publish","type":"post","link":"https:\/\/egany.com\/blogs\/frontend-du-ky-s2e3-cross-platform-apps-phan-3-co-cong-mai-sat-co-ngay-release\/","title":{"rendered":"Frontend Du K\u00fd S2E3 | Cross-platform Apps (ph\u1ea7n 3): C\u00f3 c\u00f4ng m\u00e0i s\u1eaft, c\u00f3 ng\u00e0y release"},"content":{"rendered":"<p>C\u1eafm \u0111\u1ea7u c\u1eafm c\u1ed5 d\u1ecdn d\u1eb9p deadline v\u00e0 d\u1ecdn nh\u00e0 tr\u01b0\u1edbc T\u1ebft n\u00ean ng\u00e2m b\u00e0i blog l\u00ean men lu\u00f4n r\u1ed3i. Xin l\u1ed7i m\u1ecdi ng\u01b0\u1eddi nh\u00e9. Nay r\u1ea3nh r\u1ed7i c\u00f3 ch\u00fat th\u1eddi gian tranh th\u1ee7 vi\u1ebft l\u00e1ch m\u1ed9t t\u00ed k\u1ebbo s\u1ebfp bi\u1ebft l\u1ea1i giao th\u00eam task.<\/p>\n<p>N\u1ebfu b\u1ea1n ch\u01b0a \u0111\u1ecdc t\u1eadp tr\u01b0\u1edbc, b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecdc <a href=\"https:\/\/egany.com\/blogs\/frontend-du-ky-s2e2-cross-platform-apps-phan-2-sai-1-ly-di-1-6-km\">t\u1ea1i \u0111\u00e2y<\/a>.<\/p>\n<h2>Gi\u1edbi thi\u1ec7u<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/cpa-chakra-login-1024x508.png\" alt=\"Cross-platform Apps built with ChakraUI\" \/><\/p>\n<blockquote>\n<p>Cross-platform Apps s\u1ebd \u0111\u01b0\u1ee3c vi\u1ebft t\u1eaft b\u1eb1ng CPA \u0111\u1ec3 thu\u1eadn ti\u1ec7n cho ng\u01b0\u1eddi vi\u1ebft b\u00e0i<\/p>\n<\/blockquote>\n<p>Sau khi nh\u1eadn ra v\u1ea5n \u0111\u1ec1 v\u1ec1 license (t\u1ea1m d\u1ecbch l\u00e0 gi\u1ea5y ph\u00e9p s\u1eed d\u1ee5ng) li\u00ean quan t\u1edbi Shopify Polaris, team quy\u1ebft \u0111\u1ecbnh t\u1ea1m th\u1eddi ng\u1eebng ph\u00e1t tri\u1ec3n t\u00ednh n\u0103ng m\u1edbi \u0111\u1ec3 gi\u1ea3i quy\u1ebft v\u1ea5n \u0111\u1ec1 tr\u00ean. \u0110\u00e2y c\u0169ng l\u00e0 m\u1ed9t c\u01a1 h\u1ed9i \u0111\u1ec3 team c\u00f3 th\u1ec3 nh\u00ecn l\u1ea1i v\u00e0 \u0111\u00e1nh gi\u00e1 c\u00e1c c\u00f4ng ngh\u1ec7 \u0111\u00e3 ch\u1ecdn.<\/p>\n<p><strong>Frontend Du K\u00fd<\/strong> t\u1eadp n\u00e0y s\u1ebd k\u1ec3 v\u1ec1 h\u00e0nh tr\u00ecnh \u0111i t\u00ecm nh\u1eefng c\u00f4ng ngh\u1ec7 m\u1edbi, ph\u00f9 h\u1ee3p h\u01a1n v\u1edbi m\u1ee5c ti\u00eau s\u1eafp t\u1edbi c\u1ee7a team. Ti\u00eau ch\u00ed l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 s\u1ebd bao g\u1ed3m:<\/p>\n<ul>\n<li>\u01afu ti\u00ean license MIT ho\u1eb7c c\u00e1c license t\u01b0\u01a1ng t\u1ef1, cho ph\u00e9p s\u1eed d\u1ee5ng trong c\u00e1c d\u1ef1 \u00e1n th\u01b0\u01a1ng m\u1ea1i (commercial project)<\/li>\n<li>\u0110\u1ea3m b\u1ea3o \u0111\u00e1p \u1ee9ng \u0111\u01b0\u1ee3c c\u00e1c y\u00eau c\u1ea7u v\u1ec1 t\u00ednh n\u0103ng hi\u1ec7n c\u00f3 c\u0169ng nh\u01b0 c\u00e1c t\u00ednh n\u0103ng d\u1ef1 \u0111\u1ecbnh s\u1ebd ph\u00e1t tri\u1ec3n<\/li>\n<li>D\u1ec5 s\u1eed d\u1ee5ng, d\u1ec5 ti\u1ebfp c\u1eadn \u0111\u1ec3 gi\u1ea3m thi\u1ec3u t\u1ed1i \u0111a th\u1eddi gian c\u1ea7n \u0111\u1ec3 chuy\u1ec3n \u0111\u1ed5i<\/li>\n<\/ul>\n<h2>K\u1ebf ho\u1ea1ch tri\u1ec3n khai<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2022\/02\/planning-illustration.png\" alt=\"Planning Illustration\" \/><\/p>\n<blockquote>\n<p>Ngu\u1ed3n \u1ea3nh: <a href=\"https:\/\/dribbble.com\/shots\/15135572-Scheduling-Master\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/dribbble.com\/shots\/15135572-Scheduling-Master<\/a><\/p>\n<\/blockquote>\n<p>Tho\u1ea1t \u0111\u1ea7u team ch\u1ec9 \u0111\u1ecbnh d\u00e0nh ra 2 \u0111\u1ebfn 3 tu\u1ea7n \u0111\u1ec3 \u0111\u1ed5i component kit r\u1ed3i sau \u0111\u00f3 s\u1ebd ti\u1ebfp t\u1ee5c ph\u00e1t tri\u1ec3n ti\u1ebfp tr\u00ean n\u1ec1n t\u1ea3ng \u0111\u00e3 c\u00f3 s\u1eb5n. Tuy nhi\u00ean, c\u00e1 nh\u00e2n m\u00ecnh th\u1ea5y n\u1ec1n t\u1ea3ng hi\u1ec7n t\u1ea1i ch\u01b0a \u0111\u1ee7 &quot;v\u1eefng&quot; \u0111\u1ec3 l\u00e0m n\u1ec1n m\u00f3ng cho c\u00e1c \u1ee9ng d\u1ee5ng k\u1ebf ti\u1ebfp. C\u00f3 l\u1ebd m\u1ed9t ph\u1ea7n c\u0169ng do \u0111\u1ecbnh h\u01b0\u1edbng ban \u0111\u1ea7u c\u1ee7a Cross-Platform Apps (CPA) l\u00e0 m\u1ed9t d\u1ef1 \u00e1n th\u1eed nghi\u1ec7m n\u00ean team th\u1eadt s\u1ef1 ch\u01b0a ch\u00fa tr\u1ecdng t\u1edbi vi\u1ec7c l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7, d\u1eabn \u0111\u1ebfn vi\u1ec7c g\u1eb7p v\u1ea5n \u0111\u1ec1 v\u1ec1 gi\u1ea5y ph\u00e9p nh\u01b0 m\u00ecnh \u0111\u00e3 \u0111\u1ec1 c\u1eadp.<\/p>\n<p>Ngo\u00e0i ra, sau m\u1ed9t th\u1eddi gian d\u00e0i ph\u00e1t tri\u1ec3n th\u00ec c\u00f4ng ngh\u1ec7 c\u0169ng \u0111\u00e3 b\u1ecb l\u1ed7i th\u1eddi, n\u1ebfu ti\u1ebfp t\u1ee5c s\u1eed d\u1ee5ng s\u1ebd m\u1ea5t \u0111i nhi\u1ec1u t\u00ednh n\u0103ng c\u0169ng nh\u01b0 b\u1ea3n v\u00e1 l\u1ed7i m\u1edbi c\u1ee7a th\u01b0 vi\u1ec7n\/framework \u0111ang s\u1eed d\u1ee5ng.<\/p>\n<p>Sau khi th\u1ea3o lu\u1eadn, team quy\u1ebft \u0111\u1ecbnh giao ph\u00f3 to\u00e0n b\u1ed9 tr\u1ecdng tr\u00e1ch tr\u00ean l\u00ean \u0111\u00f4i vai b\u00e9 nh\u1ecf c\u1ee7a m\u00ecnh. Th\u00f4i th\u00ec c\u0169ng \u0111\u01b0\u1ee3c. Anh\/ch\u1ecb\/em <del>\u0111\u00f9n \u0111\u1ea9y tr\u00e1ch nhi\u1ec7m<\/del> tin t\u01b0\u1edfng n\u00ean m\u00ecnh c\u0169ng c\u1ed1 g\u1eafng h\u1ebft s\u1ee9c \u0111\u1ec3 kh\u00f4ng ph\u1ee5 l\u00f2ng m\u1ecdi ng\u01b0\u1eddi.<\/p>\n<p>C\u00f9ng b\u1eaft \u0111\u1ea7u t\u00ecm qu\u00e1 tr\u00ecnh t\u00ecm hi\u1ec3u v\u00e0 th\u1eed nghi\u1ec7m c\u1ee7a m\u00ecnh nha!<\/p>\n<h2>TypeScript<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/03\/ts-logo-128.png\" alt=\"TypeScript logo\" \/><\/p>\n<p>Team \u0111\u00e3 r\u1ea5t nhi\u1ec1u l\u1ea7n \u0111\u1eafn \u0111o v\u1ec1 vi\u1ec7c c\u00f3 n\u00ean s\u1eed d\u1ee5ng TypeScript (TS) \u1edf ph\u00eda frontend hay kh\u00f4ng v\u00e0 h\u1ea7u h\u1ebft c\u00e2u tr\u1ea3 l\u1eddi \u0111\u1ec1u l\u00e0 kh\u00f4ng. Quy\u1ebft \u0111\u1ecbnh n\u00e0y ho\u00e0n to\u00e0n c\u00f3 c\u01a1 s\u1edf, b\u1ea1n c\u00f3 th\u1ec3 xem l\u1ea7n t\u1eadp tr\u01b0\u1edbc \u0111\u1ec3 hi\u1ec3u l\u00fd do v\u00ec sao team v\u1eabn s\u1eed d\u1ee5ng JavaScript (JS) \u0111\u1ec3 ph\u00e1t tri\u1ec3n. Tuy nhi\u00ean, v\u1edbi c\u1ea5u tr\u00fac d\u1eef li\u1ec7u c\u1ee7a \u1ee9ng d\u1ee5ng ng\u00e0y c\u00e0ng nhi\u1ec1u v\u00e0 ph\u1ee9c t\u1ea1p th\u00ec vi\u1ec7c s\u1eed d\u1ee5ng TS l\u00e0 m\u1ed9t l\u1ef1a ch\u1ecdn h\u1ee3p l\u00fd trong th\u1eddi \u0111i\u1ec3m n\u00e0y.<\/p>\n<p>\u0110\u00e2y l\u00e0 m\u1ed9t quy\u1ebft \u0111\u1ecbnh t\u01b0\u01a1ng \u0111\u1ed1i &quot;t\u00e1o b\u1ea1o&quot; v\u00ec b\u1ea3n th\u00e2n m\u00ecnh v\u00e0 team ch\u01b0a c\u00f3 nhi\u1ec1u kinh nghi\u1ec7m trong vi\u1ec7c s\u1eed d\u1ee5ng TS, \u0111\u1eb7c bi\u1ec7t l\u00e0 c\u00e1ch khai b\u00e1o <code>type<\/code> (ki\u1ec3u d\u1eef li\u1ec7u, v\u00ed d\u1ee5: <code>string<\/code>, <code>number<\/code>, <code>{ foo: string, bar: boolean }<\/code>) &#8211; m\u1ed9t trong nh\u1eefng y\u1ebfu t\u1ed1 quy\u1ebft \u0111\u1ecbnh m\u1ee9c \u0111\u1ed9 hi\u1ec7u qu\u1ea3 c\u1ee7a TS. D\u00f9 v\u1eady, m\u00ecnh v\u1eabn mu\u1ed1n &quot;th\u1eed sai&quot; \u0111\u1ec3 l\u1ea5y kinh nghi\u1ec7m cho c\u00e1c d\u1ef1 \u00e1n s\u1eafp t\u1edbi. Ch\u1eb3ng m\u1ea5y khi c\u00f3 \u0111\u01b0\u1ee3c c\u01a1 h\u1ed9i th\u1eed sai, ng\u1ea1i g\u00ec m\u00e0 kh\u00f4ng th\u1eed ph\u1ea3i kh\u00f4ng c\u00e1c b\u1ea1n?<\/p>\n<p>K\u1ebf ho\u1ea1ch ban \u0111\u1ea7u c\u1ee7a m\u00ecnh l\u00e0 chuy\u1ec3n d\u1ea7n c\u00e1c file JS hi\u1ec7n c\u00f3 trong d\u1ef1 \u00e1n qua TS. Tuy nhi\u00ean, sau kho\u1ea3ng 2 ti\u1ebfng khai b\u00e1o ki\u1ec3u, \u0111\u1ed5i t\u1eeb file n\u00e0y qua file kh\u00e1c c\u0169ng nh\u01b0 s\u1eeda h\u00e0ng tr\u0103m l\u1ed7i xu\u1ea5t hi\u1ec7n sau khi \u0111\u1ed5i t\u00ean file th\u00ec m\u00ecnh quy\u1ebft \u0111\u1ecbnh vi\u1ebft l\u1ea1i t\u1eeb \u0111\u1ea7u. L\u00fd do:<\/p>\n<ul>\n<li><strong><code>strict: true<\/code><\/strong>. \u0110\u1ec3 t\u1eadn d\u1ee5ng t\u1ed1i \u0111a hi\u1ec7u n\u0103ng c\u1ee7a TS th\u00ec m\u00ecnh quy\u1ebft \u0111\u1ecbnh b\u1eadt <em>strict mode<\/em> ngay t\u1eeb ban \u0111\u1ea7u. Vi\u1ec7c b\u1eadt <em>strict mode<\/em> s\u1ebd g\u00e2y kh\u00f3 kh\u0103n trong qu\u00e1 tr\u00ecnh chuy\u1ec3n \u0111\u1ed5i nh\u01b0ng n\u1ebfu quy\u1ebft \u0111\u1ecbnh vi\u1ebft l\u1ea1i t\u1eeb \u0111\u1ea7u th\u00ec m\u00ecnh tin r\u1eb1ng \u0111\u00e2y l\u00e0 m\u1ed9t quy\u1ebft \u0111\u1ecbnh h\u1ee3p l\u00fd<\/li>\n<li><strong>T\u1ed5 ch\u1ee9c l\u1ea1i c\u1ea5u tr\u00fac th\u01b0 m\u1ee5c<\/strong>. Vi\u1ec7c vi\u1ebft l\u1ea1i t\u1eeb \u0111\u1ea7u c\u0169ng gi\u00fap m\u00ecnh h\u1ec7 th\u1ed1ng h\u00f3a l\u1ea1i c\u00e1c file hi\u1ec7n c\u00f3 v\u00e0 chu\u1ea9n h\u00f3a quy t\u1eafc \u0111\u1eb7t t\u00ean file. Ngo\u00e0i c\u00e1c th\u01b0 m\u1ee5c th\u01b0\u1eddng th\u1ea5y nh\u01b0 <code>components<\/code>, <code>services<\/code>, <code>config<\/code>, <code>utils<\/code> th\u00ec m\u00ecnh c\u00f2n t\u1ea1o th\u00eam:\n<ul>\n<li><code>hooks<\/code>: ch\u1ee9a c\u00e1c <em>custom React hook<\/em> d\u00f9ng chung, ch\u1ee7 y\u1ebfu l\u00e0 c\u00e1c hook li\u00ean quan t\u1edbi vi\u1ec7c fetch (t\u1ea3i\/l\u1ea5y) d\u1eef li\u1ec7u<\/li>\n<li><code>business<\/code>: ch\u1ee9a c\u00e1c component \u0111\u1eb7c bi\u1ec7t ch\u1ec9 d\u00f9ng cho m\u1ed9t trang c\u1ee5 th\u1ec3. B\u00ean trong <code>business<\/code> s\u1ebd ph\u00e2n chia th\u01b0 m\u1ee5c con theo t\u00ean \u1ee9ng d\u1ee5ng, v\u00ed d\u1ee5: <code>\/business\/ega-shop\/<\/code><\/li>\n<li><code>stores<\/code>: ch\u1ee9a khai b\u00e1o global state (m\u00ecnh g\u1ecdi l\u00e0 store \u0111\u1ec3 gi\u1ed1ng c\u00e1ch g\u1ecdi c\u1ee7a th\u01b0 vi\u1ec7n <em>zustand<\/em> \u0111ang d\u00f9ng)<\/li>\n<\/ul>\n<\/li>\n<li><strong>D\u1ec5 qu\u1ea3n l\u00fd git v\u00e0 deploy<\/strong>. \u0110\u1ec3 v\u1eeba kh\u00f4ng \u0111\u1ee5ng ch\u1ea1m d\u1ef1 \u00e1n c\u0169 \u0111ang ch\u1ea1y (ph\u1ee5c v\u1ee5 cho tester) v\u1eeba d\u1ec5 d\u00e0ng qu\u1ea3n l\u00fd cho team dev th\u00ec vi\u1ec7c t\u00e1ch ri\u00eang m\u1ed9t repository (repo) m\u1edbi v\u00e0 vi\u1ebft l\u1ea1i t\u1eeb \u0111\u1ea7u l\u00e0 l\u1ef1a ch\u1ecdn \u0111\u00fang \u0111\u1eafn. Khi c\u00f3 2 repo ri\u00eang bi\u1ec7t th\u00ec vi\u1ec7c copy code qua l\u1ea1i c\u0169ng kh\u00e1 \u0111\u01a1n gi\u1ea3n<\/li>\n<\/ul>\n<p>D\u00f9 \u0111\u00e3 tri\u1ec3n khai theo h\u01b0\u1edbng vi\u1ebft l\u1ea1i nh\u01b0ng TS v\u1eabn g\u00e2y kh\u00e1 nhi\u1ec1u kh\u00f3 kh\u0103n cho m\u00ecnh trong l\u00fac ph\u00e1t tri\u1ec3n. M\u1ed9t trong nh\u1eefng v\u1ea5n \u0111\u1ec1 m\u00ecnh g\u1eb7p ph\u1ea3i l\u00e0 vi\u1ec7c ph\u1ea3i l\u1eb7p l\u1ea1i <em>condition<\/em> (\u0111i\u1ec1u ki\u1ec7n ki\u1ec3m tra if\/else) \u0111\u1ec3 &quot;th\u1ecfa m\u00e3n&quot; compiler c\u1ee7a TS. C\u1ee5 th\u1ec3 nh\u01b0 sau:<\/p>\n<pre><code class=\"language-typescript\">\/\/ Code ch\u1ea1y \u0111\u00fang n\u1ebfu d\u00f9ng tr\u1ef1c ti\u1ebfp &#039;condition&#039;\nfunction createMessage(str: string | null) {\n  if (typeof str === &#039;string&#039; &amp;&amp; str.trim().length &gt; 0) {\n    return str.concat(&#039; is a valid string&#039;) \/\/ ok\n  }\n}\n\n\/\/ TS b\u00e1o l\u1ed7i khi t\u00e1ch ri\u00eang &#039;condition&#039; th\u00e0nh bi\u1ebfn\nfunction createMessage(str: string | null) {\n  const isValidString = typeof str === &#039;string&#039; &amp;&amp; str.trim().length &gt; 0\n\n  if (isValidString) {\n    return str.concat(&#039; is a valid string&#039;) \/\/ error: Type of &#039;str&#039; variable might be null\n  }\n}<\/code><\/pre>\n<p>R\u1ea5t may l\u00e0 \u1edf phi\u00ean b\u1ea3n TS 4.4 th\u00ec v\u1ea5n \u0111\u1ec1 n\u00e0y \u0111\u00e3 \u0111\u01b0\u1ee3c kh\u1eafc ph\u1ee5c. C\u00e1c b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecdc th\u00eam <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-4-4\/#cfa-aliased-conditions\" rel=\"nofollow noopener\" target=\"_blank\">t\u1ea1i \u0111\u00e2y<\/a>.<\/p>\n<p>M\u1ed9t v\u1ea5n \u0111\u1ec1 kh\u00e1c m\u00ecnh c\u0169ng g\u1eb7p ph\u1ea3i trong qu\u00e1 tr\u00ecnh l\u00e0m vi\u1ec7c v\u1edbi TS l\u00e0 c\u1ea3m gi\u00e1c &quot;an to\u00e0n&quot; gi\u1ea3 do TS mang l\u1ea1i. C\u00f4ng t\u00e2m m\u00e0 n\u00f3i th\u00ec th\u1ef1c s\u1ef1 \u0111\u00e2y l\u00e0 s\u01a1 xu\u1ea5t c\u1ee7a b\u1ea3n th\u00e2n m\u00ecnh. Tuy nhi\u00ean, m\u00ecnh v\u1eabn mu\u1ed1n chia s\u1ebb \u0111i\u1ec1u n\u00e0y t\u1edbi c\u00e1c b\u1ea1n \u0111\u1ec3 c\u00e1c b\u1ea1n c\u00f3 nh\u1eadn th\u1ee9c v\u1ec1 n\u00f3 v\u00e0 tr\u00e1nh n\u00f3 trong d\u1ef1 \u00e1n c\u1ee7a c\u00e1c b\u1ea1n.<\/p>\n<p>V\u1ea5n \u0111\u1ec1 xu\u1ea5t hi\u1ec7n khi m\u00ecnh l\u00e0m vi\u1ec7c v\u1edbi d\u1eef li\u1ec7u c\u1ee7a m\u1ed9t b\u00ean \u0111\u1ed1i t\u00e1c. D\u1eef li\u1ec7u c\u1ee7a h\u1ecd nh\u01b0 sau:<\/p>\n<pre><code class=\"language-typescript\">{\n  ...,\n  price: &quot;100000&quot; \/\/ d\u1eef li\u1ec7u l\u00e0 ch\u1eef (string)\n}<\/code><\/pre>\n<p>V\u00ec m\u1ed9t l\u00fd do n\u00e0o \u0111\u00f3, m\u00ecnh \u0111\u00e3 khai b\u00e1o ki\u1ec3u nh\u01b0 sau:<\/p>\n<pre><code class=\"language-typescript\">{\n  ...,\n  price: number \/\/ khai b\u00e1o nh\u1ea7m ki\u1ec3u s\u1ed1 (number)\n}<\/code><\/pre>\n<p>Nh\u01b0 c\u00e1c b\u1ea1n c\u00f3 th\u1ec3 th\u1ea5y l\u00e0 m\u00ecnh \u0111\u00e3 khai b\u00e1o sai ki\u1ec3u d\u1eef li\u1ec7u cho thu\u1ed9c t\u00ednh <code>price<\/code>. TS s\u1ebd kh\u00f4ng b\u00e1o l\u1ed7i cho ch\u00fang ta \u1edf tr\u01b0\u1eddng h\u1ee3p n\u00e0y v\u00ec v\u1ec1 l\u00fd thuy\u1ebft th\u00ec code kh\u00f4ng h\u1ec1 sai. B\u1ea3n th\u00e2n m\u00ecnh c\u0169ng kh\u00e1 ch\u1ee7 quan, kh\u00f4ng ki\u1ec3m tra l\u1ea1i type c\u1ee7a bi\u1ebfn <code>price<\/code> khi s\u1eed d\u1ee5ng, d\u1eabn \u0111\u1ebfn c\u00e1c ph\u00e9p t\u00ednh to\u00e1n c\u1ed9ng \u0111\u1ec1u b\u1ecb sai (ph\u00e9p c\u1ed9ng s\u1ebd \u0111\u01b0\u1ee3c hi\u1ec3u l\u00e0 gh\u00e9p chu\u1ed7i).<\/p>\n<p>Trong c\u00e1i r\u1ee7i c\u00f3 c\u00e1i may. V\u00ec d\u1ef1 \u00e1n v\u1eabn \u0111ang trong qu\u00e1 tr\u00ecnh ph\u00e1t tri\u1ec3n n\u00ean s\u1ef1 c\u1ed1 tr\u00ean kh\u00f4ng g\u00e2y t\u1ed5n h\u1ea1i t\u1edbi kh\u00e1ch h\u00e0ng. D\u00f9 v\u1eady, \u0111\u00e2y c\u0169ng l\u00e0 h\u1ed3i chu\u00f4ng c\u1ea3nh t\u1ec9nh \u0111\u1ec3 m\u00ecnh \u0111\u1ec3 t\u00e2m h\u01a1n \u0111\u1ebfn vi\u1ec7c ki\u1ec3m tra ki\u1ec3u c\u1ee7a d\u1eef li\u1ec7u, \u0111\u1eb7c bi\u1ec7t l\u00e0 \u0111\u1ed1i v\u1edbi d\u1eef li\u1ec7u b\u00ean ngo\u00e0i.<\/p>\n<h2>Ant Design<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/antd-thumb.jpg\" alt=\"Ant Design logo\" \/><\/p>\n<p>Vi\u1ec7c thay \u0111\u1ed5i ng\u00f4n ng\u1eef qua TypeScript trong l\u1ea7n chuy\u1ec3n \u0111\u1ed5i n\u00e0y th\u1ef1c ch\u1ea5t c\u0169ng nh\u01b0 c\u00e2u t\u1ee5c ng\u1eef &quot;th\u1eeba n\u01b0\u1edbc \u0111\u1ee5c th\u1ea3 c\u00e2u&quot; m\u00e0 th\u00f4i. S\u1eb5n ti\u1ec7n chuy\u1ec3n \u0111\u1ed5i th\u00ec l\u00e0m lu\u00f4n ph\u1ea3i kh\u00f4ng c\u00e1c b\u1ea1n?<\/p>\n<p>T\u00e2m \u0111i\u1ec3m ch\u00ednh c\u1ee7a l\u1ea7n chuy\u1ec3n \u0111\u1ed5i n\u00e0y v\u1eabn l\u00e0 UI component, c\u1ee5 th\u1ec3 h\u01a1n l\u00e0 vi\u1ec7c thay th\u1ebf Shopify Polaris b\u1eb1ng m\u1ed9t UI component kit kh\u00e1c. V\u00ec \u0111\u00e3 t\u1eebng tr\u1ea3i nghi\u1ec7m v\u00e0 \u00e1p d\u1ee5ng s\u01a1 AntDesign trong m\u1ed9t d\u1ef1 \u00e1n outsource \u1edf c\u00f4ng ty r\u1ed3i n\u00ean m\u00ecnh quy\u1ebft \u0111\u1ecbnh ch\u1ecdn AntDesign \u0111\u1ec3 thay th\u1ebf Shopify Polaris.<\/p>\n<p>M\u1ed9t s\u1ed1 \u01b0u \u0111i\u1ec3m c\u1ee7a AntDesign:<\/p>\n<ul>\n<li><strong>Component phong ph\u00fa<\/strong>. Danh s\u00e1ch component c\u1ee7a AntDesign kh\u00e1 \u0111\u1ed3 s\u1ed9 v\u00e0 \u0111a d\u1ea1ng, \u0111\u00e1p \u1ee9ng \u0111\u1ee7 v\u00e0 th\u1eadm ch\u00ed l\u00e0 &quot;d\u01b0 d\u1ea3&quot; cho nh\u1eefng d\u1ef1 \u0111\u1ecbnh t\u01b0\u01a1ng lai c\u1ee7a team<\/li>\n<li><strong>H\u1ec7 th\u1ed1ng form chuy\u00ean nghi\u1ec7p<\/strong>. M\u00ecnh kh\u00e1 \u01b0ng \u00fd v\u1edbi h\u1ec7 th\u1ed1ng form c\u1ee7a AntDesign. Ngo\u00e0i vi\u1ec7c h\u1ed7 tr\u1ee3 v\u1ec1 giao di\u1ec7n th\u00ec form c\u00f2n h\u1ed7 tr\u1ee3 v\u1ec1 vi\u1ec7c qu\u1ea3n l\u00fd d\u1eef li\u1ec7u trong form v\u00e0 h\u1ed7 tr\u1ee3 lu\u00f4n c\u00e1c lo\u1ea1i x\u00e1c th\u1ef1c d\u1eef li\u1ec7u (validation) c\u01a1 b\u1ea3n c\u0169ng nh\u01b0 n\u00e2ng cao. Kh\u00f4ng c\u00f2n c\u1ea3nh ph\u1ea3i t\u1ef1 t\u1ed5 ch\u1ee9c d\u1eef li\u1ec7u b\u1eb1ng state hay reducer nh\u01b0 tr\u01b0\u1edbc n\u1eefa, m\u00ecnh ch\u1ec9 c\u1ea7n g\u1eafn event handler l\u00e0 \u0111\u00e3 c\u00f3 th\u1ec3 thu th\u1eadp d\u1eef li\u1ec7u c\u1ee7a h\u00e0ng ch\u1ee5c, h\u00e0ng tr\u0103m th\u00f4ng tin c\u00f3 trong form r\u1ed3i<\/li>\n<li><strong>C\u00f3 t\u1eadp \u0111o\u00e0n l\u1edbn &quot;ch\u1ed1ng l\u01b0ng&quot;<\/strong>. AntDesign l\u00e0 m\u1ed9t s\u1ea3n ph\u1ea9m c\u1ee7a t\u1eadp \u0111o\u00e0n Ant n\u00ean vi\u1ec7c m\u1ed9t ng\u00e0y n\u00e0o \u0111\u00f3 AntDesign bi\u1ebfn m\u1ea5t c\u0169ng kh\u00e1 kh\u00f3 x\u1ea3y ra. Vi\u1ec7c n\u00e0y c\u0169ng khi\u1ebfn m\u00ecnh y\u00ean t\u00e2m h\u01a1n trong qu\u00e1 tr\u00ecnh ph\u00e1t tri\u1ec3n l\u00e2u d\u00e0i, \u00edt nh\u1ea5t l\u00e0 trong 2 t\u1edbi 3 n\u0103m ti\u1ebfp theo<\/li>\n<\/ul>\n<p>Sau khi \u0111\u01b0\u1ee3c &quot;thuy\u1ebft ph\u1ee5c&quot; b\u1edfi nh\u1eefng \u0111i\u1ec1u tr\u00ean, m\u00ecnh b\u1eaft \u0111\u1ea7u chuy\u1ec3n \u0111\u1ed5i to\u00e0n b\u1ed9 giao di\u1ec7n c\u1ee7a CPA. Qu\u00e1 tr\u00ecnh chuy\u1ec3n \u0111\u1ed5i c\u0169ng kh\u00e1 \u0111\u01a1n gi\u1ea3n, th\u1eadm ch\u00ed l\u00e0 \u0111\u01a1n gi\u1ea3n h\u01a1n so v\u1edbi khi s\u1eed d\u1ee5ng Shopify Polaris v\u00ec l\u01b0\u1ee3ng component phong ph\u00fa c\u1ee7a AntDesign, m\u00ecnh kh\u00f4ng c\u1ea7n ph\u1ea3i t\u1ea1o custom component n\u00e0o c\u1ea3. Kh\u00f3 kh\u0103n l\u1edbn nh\u1ea5t l\u00fac b\u1ea5y gi\u1edd c\u00f3 l\u1ebd l\u00e0 vi\u1ec7c chuy\u1ec3n \u0111\u1ed5i form. M\u00ecnh ph\u1ea3i chuy\u1ec3n ph\u1ea7n state c\u0169 &#8211; qu\u1ea3n l\u00fd b\u1eb1ng tay qua h\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd form c\u1ee7a AntDesign. Ch\u00ednh t\u1ea1i \u0111\u00e2y th\u00ec m\u00ecnh ph\u00e1t hi\u1ec7n ra m\u1ed9t s\u1ed1 \u0111i\u1ec3m y\u1ebfu c\u1ee7a AntDesign m\u00e0 m\u00ecnh kh\u00f4ng nh\u1eadn ra tr\u01b0\u1edbc \u0111\u00f3<\/p>\n<ul>\n<li><strong>C\u00fa ph\u00e1p (syntax) r\u01b0\u1eddm r\u00e0<\/strong>. N\u1ebfu nh\u01b0 form c\u1ee7a b\u1ea1n \u0111\u01a1n gi\u1ea3n, AntDesign \u0111\u00e1p \u1ee9ng r\u1ea5t t\u1ed1t \u1edf \u0111i\u1ec3m n\u00e0y. Tuy nhi\u00ean, n\u1ebfu form c\u1ee7a b\u1ea1n ph\u1ee9c t\u1ea1p, c\u00e1c tr\u01b0\u1eddng (field) trong form thay \u0111\u1ed5i d\u1ef1a tr\u00ean d\u1eef li\u1ec7u ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o th\u00ec code ph\u00e1t sinh ph\u00ecnh ra r\u1ea5t nhi\u1ec1u. V\u00ed d\u1ee5 \u0111\u01a1n gi\u1ea3n:<\/li>\n<\/ul>\n<pre><code class=\"language-javascript\">\/\/ - isEnabled: switch on\/off\n\/\/ - optionalField: \u1ea9n\/hi\u1ec7n t\u00f9y thu\u1ed9c v\u00e0o tr\u1ea1ng th\u00e1i c\u1ee7a &#039;isEnabled&#039;\n\n\/\/ Shopify Polaris (form state t\u1ef1 qu\u1ea3n)\n{\n  formValues.isEnabled &amp;&amp; (\n    &lt;Input value={value} onChange={handleFieldChange(&#039;optionalField&#039;)} \/&gt;\n  )\n}\n\n\/\/ AntDesign (form state c\u00f3 s\u1eb5n)\n&lt;Form.Item\n  noStyle\n  shouldUpdate={(prevValues, curValues) =&gt;\n    prevValues.isEnabled !== curValues.isEnabled\n  }\n>\n  {({ getFieldValue }) =&gt; {\n    if (!getFieldValue(&#039;isEnabled&#039;)) {\n      return null\n    }\n\n    return (\n      &lt;Form.Item label=&quot;Optional field&quot; name=&quot;optionalField&quot;&gt;\n        &lt;Input \/&gt;\n      &lt;\/Form.Item&gt;\n    )\n  }}\n&lt;\/Form.Item&gt;<\/code><\/pre>\n<ul>\n<li><strong>Ch\u1ec9 nh\u1eadn gi\u00e1 tr\u1ecb tr\u01b0\u1eddng \u0111ang hi\u1ec3n th\u1ecb<\/strong>. M\u1eb7c \u0111\u1ecbnh AntDesign s\u1ebd x\u00f3a th\u00f4ng tin c\u00e1c tr\u01b0\u1eddng kh\u00f4ng \u0111\u01b0\u1ee3c render tr\u00ean m\u00e0n h\u00ecnh. V\u00ed d\u1ee5 nh\u01b0 tr\u01b0\u1eddng h\u1ee3p tr\u00ean th\u00ec tr\u01b0\u1eddng <code>optionalField<\/code> s\u1ebd b\u1ecb x\u00f3a khi submit n\u1ebfu <code>isEnabled<\/code> c\u00f3 gi\u00e1 tr\u1ecb l\u00e0 <code>false<\/code>. \u0110i\u1ec1u n\u00e0y g\u00e2y c\u1ea3n tr\u1edf kh\u00e1 nhi\u1ec1u v\u00ec giao di\u1ec7n ph\u00eda m\u00ecnh \u0111\u01b0\u1ee3c chia th\u00e0nh nhi\u1ec1u tab, \u0111\u1ed3ng ngh\u0129a v\u1edbi vi\u1ec7c khi submit th\u00ec ch\u1ec9 submit \u0111\u01b0\u1ee3c tab \u0111ang m\u1edf m\u00e0 th\u00f4i. \u0110\u1ec3 ch\u1ea1y \u0111\u01b0\u1ee3c ch\u1ed7 n\u00e0y th\u00ec m\u00ecnh ph\u1ea3i &quot;b\u00f9a ch\u00fa&quot; m\u1ed9t ch\u00fat b\u1eb1ng c\u00e1ch render lu\u00f4n c\u00e1c tr\u01b0\u1eddng \u1ea9n v\u00e0 th\u00eam thu\u1ed9c t\u00ednh <code>display: none<\/code>. Tuy kh\u00f4ng \u1ea3nh h\u01b0\u1edfng qu\u00e1 nhi\u1ec1u t\u1edbi hi\u1ec7u n\u0103ng c\u1ee7a trang nh\u01b0ng vi\u1ec7c ph\u1ea3i \u0111\u1ec3 t\u00e2m t\u1edbi &quot;t\u00ednh n\u0103ng&quot; n\u00e0y khi ph\u00e1t tri\u1ec3n UI kh\u00e1 l\u00e0 kh\u00f3 ch\u1ecbu v\u00e0 th\u1eadt l\u00f2ng m\u00e0 n\u00f3i th\u00ec kh\u00f4ng n\u00ean c\u00f3<\/li>\n<li><strong>Kh\u00f3 t\u00f9y ch\u1ec9nh theme<\/strong>. \u0110\u1ec3 ph\u00e1t tri\u1ec3n h\u00ecnh \u1ea3nh c\u00f4ng ty th\u00ec team m\u00ecnh c\u00f3 nhu c\u1ea7u t\u00f9y ch\u1ec9nh theme c\u1ee7a component (m\u00e0u s\u1eafc, font, &#8230;). Tuy nhi\u00ean, AntDesign kh\u00e1 h\u1ea1n ch\u1ebf v\u1ec1 vi\u1ec7c n\u00e0y. N\u1ebfu m\u00ecnh mu\u1ed1n t\u00f9y ch\u1ec9nh theme th\u00ec ph\u1ea3i c\u00e0i \u0111\u1eb7t th\u00eam c\u00e1c th\u01b0 vi\u1ec7n kh\u00e1c \u0111\u1ec3 h\u1ed7 tr\u1ee3 build v\u1edbi LESS. Ngo\u00e0i ra th\u00ec vi\u1ec7c chuy\u1ec3n \u0111\u1ed5i gi\u1eefa light\/dark theme c\u0169ng ph\u1ea3i ch\u1ecdn ngay t\u1eeb l\u00fac build, kh\u00e1 g\u00f2 b\u00f3 \u1edf \u0111i\u1ec3m n\u00e0y<\/li>\n<li><strong>\u0110a d\u1ea1ng ng\u00f4n ng\u1eef<\/strong>. C\u00f3 l\u1ebd c\u00e1c b\u1ea1n th\u1eafc m\u1eafc t\u1ea1i sao \u0111\u00e2y l\u1ea1i l\u00e0 m\u1ed9t kh\u00f3 kh\u0103n ph\u1ea3i kh\u00f4ng? \u0110a d\u1ea1ng ng\u00f4n ng\u1eef \u1edf \u0111\u00e2y kh\u00f4ng c\u00f3 ngh\u0129a l\u00e0 h\u1ed7 tr\u1ee3 nhi\u1ec1u ng\u00f4n ng\u1eef kh\u00e1c nhau m\u00e0 c\u00f3 ngh\u0129a l\u00e0 s\u1eed d\u1ee5ng c\u00f9ng l\u00fac nhi\u1ec1u ng\u00f4n ng\u1eef, c\u1ee5 th\u1ec3 l\u00e0 ti\u1ebfng Trung v\u00e0 ti\u1ebfng Anh trong t\u00e0i li\u1ec7u c\u0169ng nh\u01b0 tr\u00ean c\u1ed9ng \u0111\u1ed3ng \u1edf GitHub. Th\u1ec9nh tho\u1ea3ng c\u00e1c b\u1ea1n s\u1ebd th\u1ea5y m\u1ed9t s\u1ed1 t\u1eeb ti\u1ebfng Trung xu\u1ea5t hi\u1ec7n trong t\u00e0i li\u1ec7u v\u00e0 th\u01b0\u1eddng xuy\u00ean th\u1ea5y c\u00e1c issue tr\u00ean GitHub vi\u1ebft ho\u00e0n to\u00e0n b\u1eb1ng ti\u1ebfng Trung. R\u1ea5t c\u00f3 th\u1ec3 \u0111\u00f3 l\u00e0 l\u1ed7i b\u1ea1n \u0111ang t\u00ecm ki\u1ebfm nh\u01b0ng v\u00ec kh\u00f4ng hi\u1ec3u ti\u1ebfng Trung n\u00ean b\u1ea1n s\u1ebd kh\u00f4ng th\u1ec3 ti\u1ebfp c\u1eadn \u0111\u01b0\u1ee3c gi\u1ea3i ph\u00e1p cho v\u1ea5n \u0111\u1ec1 \u0111\u1ea5y. Google Translate c\u0169ng kh\u00f3 c\u00f3 th\u1ec3 c\u1ee9u b\u1ea1n trong tr\u01b0\u1eddng h\u1ee3p n\u00e0y v\u00ec ti\u1ebfng Trung theo m\u00ecnh \u0111\u00e1nh gi\u00e1 l\u00e0 m\u1ed9t ng\u00f4n ng\u1eef ph\u1ee9c t\u1ea1p, ch\u01b0a k\u1ec3 c\u00f2n c\u00f3 nhi\u1ec1u d\u1ea1ng kh\u00e1c nhau n\u00ean d\u1ecbch kh\u00f4ng \u0111\u00fang \u00fd ng\u01b0\u1eddi vi\u1ebft \u0111\u01b0\u1ee3c<\/li>\n<\/ul>\n<p>D\u00f9 v\u1eady, v\u00ec m\u1ed9t l\u00fd do g\u00ec \u0111\u1ea5y th\u00ec m\u00ecnh v\u1eabn ti\u1ebfp t\u1ee5c s\u1eed d\u1ee5ng AntDesign \u0111\u1ec3 chuy\u1ec3n \u0111\u1ed5i ho\u00e0n ch\u1ec9nh h\u1ec7 th\u1ed1ng CPA. Qu\u00e1 tr\u00ecnh n\u00e0y m\u1ea5t kho\u1ea3ng m\u1ed9t tu\u1ea7n. Sau khi b\u00e0n giao cho team tester th\u00ec m\u00ecnh l\u1ea1i x\u00e1ch balo l\u00ean v\u00e0 \u0111i t\u00ecm m\u1ed9t UI component kit kh\u00e1c ph\u00f9 h\u1ee3p h\u01a1n. N\u1ebfu ti\u1ebfp t\u1ee5c s\u1eed d\u1ee5ng AntDesign \u0111\u1ec3 ph\u00e1t tri\u1ec3n th\u00ec m\u00ecnh tin l\u00e0 s\u1ebd c\u00f3 r\u1ea5t nhi\u1ec1u v\u1ea5n \u0111\u1ec1 v\u00e0 gi\u1edbi h\u1ea1n k\u1ef9 thu\u1eadt kh\u00f4ng \u0111\u00e1ng c\u00f3 trong t\u01b0\u01a1ng lai.<\/p>\n<h2>ChakraUI + React-hook-form<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2022\/02\/chakraui-logo-150x150.png\" alt=\"ChakraUI logo\" \/> <img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2022\/02\/react-hook-form-logo-150x150.png\" alt=\"React Hook Form logo\" \/><\/p>\n<p>M\u1ed9t ng\u00e0y b\u00ecnh th\u01b0\u1eddng nh\u01b0 m\u1ed9t ng\u00e0y kh\u00e1c, khi d\u1ea1o ch\u01a1i tr\u00ean <a href=\"https:\/\/bestofjs.org\/\" title=\"Best Of JS\" rel=\"nofollow noopener\" target=\"_blank\">Best Of JS<\/a> th\u00ec m\u00ecnh b\u1eaft g\u1eb7p ChakraUI. Sau khi xem s\u01a1 qua th\u00ec nh\u1eadn \u0111\u1ecbnh c\u1ee7a m\u00ecnh nh\u01b0 sau:<\/p>\n<ul>\n<li><strong>C\u01a1 b\u1ea3n, kh\u00f4ng nhi\u1ec1u component<\/strong>. So v\u1edbi AntDesign th\u00ec l\u01b0\u1ee3ng component c\u1ee7a ChakraUI \u00edt h\u01a1n h\u1eb3n v\u00e0 kh\u00f4ng \u0111a d\u1ea1ng b\u1eb1ng<\/li>\n<li><strong>Tailwind \u1edf d\u1ea1ng component<\/strong>. T\u1eebng l\u00e0m vi\u1ec7c v\u1edbi c\u00e1c th\u01b0 vi\u1ec7n functional CSS n\u00ean m\u00ecnh c\u0169ng kh\u00e1 th\u00edch vi\u1ec7c ChakraUI h\u1ed7 tr\u1ee3 API d\u1ef1a tr\u00ean Tailwind. C\u00f3 l\u1ebd \u0111\u00e2y c\u0169ng l\u00e0 m\u1ed9t trong nh\u1eefng l\u00fd do v\u00ec sao ChakraUI thi\u1ebft k\u1ebf kh\u00e1 \u0111\u01a1n gi\u1ea3n v\u00ec n\u1ebfu thi\u1ebft k\u1ebf c\u00e0ng ph\u1ee9c t\u1ea1p th\u00ec ng\u01b0\u1eddi s\u1eed d\u1ee5ng (developer) c\u00e0ng ph\u1ea3i custom nhi\u1ec1u<\/li>\n<li><strong>T\u00f9y ch\u1ec9nh theme d\u1ec5 d\u00e0ng<\/strong>. Vi\u1ec7c t\u00f9y ch\u1ec9nh theme cho ChakraUI kh\u00e1 \u0111\u01a1n gi\u1ea3n, b\u1ea1n ch\u1ec9 c\u1ea7n khai b\u00e1o th\u00f4ng s\u1ed1 theme v\u00e0o file config l\u00e0 xong r\u1ed3i. M\u1ed9t \u0111i\u1ec3m c\u1ed9ng n\u1eefa c\u1ee7a ChakraUI l\u00e0 h\u1ed7 tr\u1ee3 light\/dark theme ngay t\u1eeb \u0111\u1ea7u v\u00e0 c\u00f3 s\u1eb5n script \u0111\u1ec3 hi\u1ec3n th\u1ecb n\u00fat chuy\u1ec3n ch\u1ebf \u0111\u1ed9 n\u1ebfu b\u1ea1n c\u00f3 nhu c\u1ea7u<\/li>\n<li><strong>Kh\u00f4ng c\u00f3 h\u1ed7 tr\u1ee3 qu\u1ea3n l\u00fd form<\/strong>. ChakraUI ch\u1ec9 t\u1eadp trung x\u1eed l\u00fd v\u1ec1 UI n\u00ean kh\u00f4ng c\u00f3 h\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd form nh\u01b0 AntDesign. Tuy v\u1eady, ChakraUI h\u1ed7 tr\u1ee3 s\u1eb5n cho c\u00e1c nhu c\u1ea7u b\u00e1o l\u1ed7i, b\u00e1o tr\u01b0\u1eddng r\u00e0ng bu\u1ed9c, &#8230; r\u1ea5t t\u1ed1t n\u00ean b\u1ea1n c\u00f3 th\u1ec3 d\u1ec5 d\u00e0ng t\u00edch h\u1ee3p form state c\u00f3 s\u1eb5n ho\u1eb7c m\u1ed9t th\u01b0 vi\u1ec7n qu\u1ea3n l\u00fd form b\u00ean ngo\u00e0i m\u00e0 kh\u00f4ng g\u1eb7p ph\u1ea3i kh\u00f3 kh\u0103n g\u00ec c\u1ea3<\/li>\n<\/ul>\n<p>Nh\u1eadn th\u1ea5y ChakraUI c\u00f2n thi\u1ebfu s\u00f3t kh\u00e1 nhi\u1ec1u, m\u00ecnh quy\u1ebft \u0111\u1ecbnh \u0111\u1ec3 n\u00f3 qua m\u1ed9t b\u00ean v\u00e0 ti\u1ebfp t\u1ee5c t\u00ecm hi\u1ec3u c\u00e1c c\u00f4ng ngh\u1ec7 kh\u00e1c \u0111\u1ec3 ph\u1ee5 tr\u1ee3. C\u00e1c component c\u00f2n thi\u1ebfu m\u00ecnh v\u00e0 team ho\u00e0n to\u00e0n c\u00f3 th\u1ec3 b\u1ed5 sung th\u00eam. Tuy nhi\u00ean, m\u00ecnh v\u1eabn mu\u1ed1n c\u00f3 m\u1ed9t h\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd form ho\u00e0n ch\u1ec9nh \u0111\u1ec3 s\u1eed d\u1ee5ng. H\u1ec7 th\u1ed1ng t\u1ef1 d\u1ef1ng hi\u1ec7n t\u1ea1i kh\u00e1 h\u1ea1n ch\u1ebf v\u00e0 hi\u1ec7u n\u0103ng kh\u00f4ng cao \u0111\u1ed1i v\u1edbi nh\u1eefng form l\u1edbn.<\/p>\n<p>L\u00fac b\u1ea5y gi\u1edd c\u00f3 kh\u00e1 nhi\u1ec1u th\u01b0 vi\u1ec7n qu\u1ea3n l\u00fd form. M\u00ecnh c\u00f3 d\u00f9ng qua m\u1ed9t s\u1ed1 th\u01b0 vi\u1ec7n th\u00ec c\u1ea3m th\u1ea5y API v\u1eabn ch\u01b0a ph\u00f9 h\u1ee3p l\u1eafm. Ngay l\u00fac \u0111\u1ecbnh b\u1ecf cu\u1ed9c th\u00ec m\u00ecnh t\u00ecm th\u1ea5y React Hook Form. V\u1edbi m\u1ed9t ng\u01b0\u1eddi &quot;nghi\u1ec7n&quot; s\u1eed d\u1ee5ng hook nh\u01b0 m\u00ecnh th\u00ec React Hook Form ch\u1eb3ng kh\u00e1c g\u00ec t\u00ecnh y\u00eau s\u00e9t \u0111\u00e1nh. \u0110\u00e1nh gi\u00e1 s\u01a1 b\u1ed9 c\u1ee7a m\u00ecnh v\u1ec1 React Hook Form:<\/p>\n<ul>\n<li><strong>Hook based<\/strong>. Hi\u1ec3u m\u1ed9t c\u00e1ch kh\u00e1c th\u00ec thay v\u00ec qu\u1ea3n l\u00fd form d\u1ef1a tr\u00ean component th\u00ec React Hook Form s\u1eed d\u1ee5ng hook. V\u1ec1 b\u1ea3n ch\u1ea5t th\u00ec c\u0169ng kh\u00f4ng c\u00f3 kh\u00e1c bi\u1ec7t g\u00ec qu\u00e1 l\u1edbn v\u1ec1 hi\u1ec7u n\u0103ng nh\u01b0ng m\u00ecnh th\u00edch s\u1eed d\u1ee5ng hook h\u01a1n, code m\u00ecnh &quot;s\u1ea1ch&quot; h\u01a1n m\u1ed9t t\u00ed so v\u1edbi s\u1eed d\u1ee5ng component. \u0110\u00e2y ho\u00e0n to\u00e0n l\u00e0 \u0111\u00e1nh gi\u00e1 ch\u1ee7 quan<\/li>\n<li><strong>Hi\u1ec7u n\u0103ng cao<\/strong>. So v\u1edbi c\u00e1c th\u01b0 vi\u1ec7n hi\u1ec7n c\u00f3 tr\u00ean th\u1ecb tr\u01b0\u1eddng th\u00ec React Hook Form c\u00f3 hi\u1ec7u n\u0103ng v\u01b0\u1ee3t tr\u1ed9i h\u01a1n h\u1eb3n khi s\u1eed d\u1ee5ng uncontrolled input. V\u1ec1 controlled component th\u00ec m\u00ecnh kh\u00f4ng th\u1ea5y \u0111\u1ec1 c\u1eadp nh\u01b0ng qua qu\u00e1 tr\u00ecnh tr\u1ea3i nghi\u1ec7m th\u00ec th\u1ea5y c\u0169ng kh\u00e1 \u1ed5n<\/li>\n<li><strong>D\u1ec5 t\u00edch h\u1ee3p<\/strong>. API c\u1ee7a React Hook Form kh\u00e1 \u00edt, \u0111\u01a1n gi\u1ea3n v\u00e0 t\u01b0\u01a1ng \u0111\u1ed1i d\u1ec5 d\u00f9ng. M\u00ecnh ch\u1ec9 t\u1ed1n kho\u1ea3ng 10 ph\u00fat \u0111\u1ec3 l\u00e0m quen v\u00e0 x\u1eed l\u00fd c\u00e1c d\u1ea1ng form ph\u1ee9c t\u1ea1p hi\u1ec7n c\u00f3 trong d\u1ef1 \u00e1n<\/li>\n<\/ul>\n<p>R\u00fat kinh nghi\u1ec7m \u1edf l\u1ea7n tr\u01b0\u1edbc, d\u00f9 l\u00e0 t\u00ecnh y\u00eau s\u00e9t \u0111\u00e1nh \u0111i ch\u0103ng n\u1eefa th\u00ec m\u00ecnh v\u1eabn mu\u1ed1n ki\u1ec3m ch\u1ee9ng l\u1ea1i \u0111\u1ec3 \u0111\u1ea3m b\u1ea3o qu\u00e1 tr\u00ecnh \u00e1p d\u1ee5ng v\u00e0o d\u1ef1 \u00e1n th\u1eadt kh\u00f4ng g\u1eb7p v\u1ea5n \u0111\u1ec1 g\u00ec c\u1ea3. V\u00e0 \u0111\u00fang nh\u01b0 m\u00ecnh d\u1ef1 \u0111o\u00e1n, v\u1eabn c\u00f3 m\u1ed9t s\u1ed1 v\u1ea5n \u0111\u1ec1 khi k\u1ebft h\u1ee3p ChakraUI v\u00e0 React Hook Form:<\/p>\n<ul>\n<li><strong>Kh\u00f4ng submit tr\u01b0\u1eddng \u1ea9n ho\u1eb7c disabled<\/strong>. \u0110\u1ec3 c\u00e1c b\u1ea1n kh\u00f4ng hi\u1ec3u sai th\u00ec tr\u01b0\u1eddng \u1ea9n \u1edf \u0111\u00e2y l\u00e0 tr\u01b0\u1eddng kh\u00f4ng \u0111\u01b0\u1ee3c render. \u0110i\u1ec3m y\u1ebfu n\u00e0y c\u0169ng gi\u1ed1ng nh\u01b0 AntDesign. Ngo\u00e0i ra th\u00ec React Hook Form s\u1ebd t\u1ef1 lo\u1ea1i b\u1ecf c\u00e1c tr\u01b0\u1eddng b\u1ecb disabled lu\u00f4n. \u0110\u00e2y l\u00e0 h\u00e0nh vi b\u00ecnh th\u01b0\u1eddng c\u1ee7a HTML, kh\u00f4ng c\u00f3 g\u00ec l\u00e0 sai c\u1ea3 n\u00ean m\u00ecnh c\u0169ng kh\u00f4ng qu\u00e1 quan ng\u1ea1i v\u1ec1 n\u00f3. Ch\u1ec9 c\u1ea7n \u0111\u1ed5i disabled th\u00e0nh readonly l\u00e0 gi\u1ea3i quy\u1ebft \u0111\u01b0\u1ee3c r\u1ed3i<\/li>\n<li><strong>D\u1eef li\u1ec7u array m\u1eb7c \u0111\u1ecbnh l\u00e0 uncontrolled<\/strong>. V\u00ec l\u00fd do hi\u1ec7u n\u0103ng n\u00ean React Hook Form m\u1eb7c \u0111\u1ecbnh xem d\u1eef li\u1ec7u array l\u00e0 uncontrolled. Vi\u1ec7c n\u00e0y \u1ea3nh h\u01b0\u1edfng kha kh\u00e1 t\u1edbi qu\u00e1 tr\u00ecnh x\u1eed l\u00fd giao di\u1ec7n c\u1ee7a ph\u00eda m\u00ecnh, c\u1ee5 th\u1ec3 l\u00e0 trong t\u00ednh n\u0103ng &quot;H\u1ee7y thay \u0111\u1ed5i&quot; (revert changes). V\u00ec d\u1eef li\u1ec7u l\u00e0 uncontrolled n\u00ean khi revert s\u1ebd kh\u00f4ng thay \u0111\u1ed5i theo state m\u1edbi nh\u1ea5t. \u0110\u1ec3 m\u00ecnh v\u00ed d\u1ee5 c\u1ee5 th\u1ec3 cho c\u00e1c b\u1ea1n d\u1ec5 hi\u1ec3u h\u01a1n nha:<\/li>\n<\/ul>\n<pre><code class=\"language-javascript\">\/\/ D\u1eef li\u1ec7u ban \u0111\u1ea7u\nlet todos = [&#039;T\u00ecm UI component kit&#039;, &#039;T\u00ecm th\u01b0 vi\u1ec7n form management&#039;]\n\/\/ =&gt; Render ra 2 d\u00f2ng v\u1edbi ti\u00eau \u0111\u1ec1 nh\u01b0 tr\u00ean\n\n\/\/ M\u00ecnh th\u00eam m\u1edbi m\u1ed9t todo\ntodos = [\n  &#039;T\u00ecm UI component kit&#039;,\n  &#039;T\u00ecm th\u01b0 vi\u1ec7n form management&#039;,\n  &#039;T\u00edch h\u1ee3p ChakraUI v\u00e0 React Hook Form&#039;\n]\n\/\/ =&gt; Render ra 3 d\u00f2ng\n\n\/\/ M\u00ecnh \u0111\u1ed5i \u00fd, ti\u1ebfn h\u00e0nh &quot;H\u1ee7y thay \u0111\u1ed5i&quot;\ntodos = [&#039;T\u00ecm UI component kit&#039;, &#039;T\u00ecm th\u01b0 vi\u1ec7n form management&#039;]\n\/\/ =&gt; V\u1eabn render ra 3 d\u00f2ng v\u00ec state kh\u00f4ng \u0111\u01b0\u1ee3c c\u1eadp nh\u1eadt<\/code><\/pre>\n<p>C\u1ea3m th\u1ea5y h\u01a1i ti\u1ebfc nu\u1ed1i cho m\u1ed9t th\u01b0 vi\u1ec7n t\u1ed1t nh\u01b0 React Hook Form, m\u00ecnh quy\u1ebft \u0111\u1ecbnh l\u00ean ph\u1ea7n Discussion c\u1ee7a React Hook Form \u0111\u1ec3 nh\u1edd h\u1ed7 tr\u1ee3 v\u00e0 v\u00f4 t\u00ecnh tr\u1edf th\u00e0nh <a href=\"https:\/\/github.com\/react-hook-form\/react-hook-form\/discussions\/5340\" rel=\"nofollow noopener\" target=\"_blank\">&quot;h\u1ed7 tr\u1ee3 vi\u00ean&quot; c\u1ee7a React Hook Form<\/a> lu\u00f4n. C\u0169ng nh\u1edd v\u1eady m\u00e0 c\u00e1c v\u1ea5n \u0111\u1ec1 v\u1ec1 x\u00f3a tr\u01b0\u1eddng \u1ea9n ho\u1eb7c d\u1eef li\u1ec7u array c\u0169ng d\u1ea7n \u0111\u01b0\u1ee3c x\u1eed l\u00fd. M\u00ecnh th\u00ec c\u00f3 th\u00eam m\u1ed9t ng\u01b0\u1eddi b\u1ea1n. M\u1ed9t c\u00f4ng \u0111\u00f4i vi\u1ec7c ph\u1ea3i kh\u00f4ng c\u00e1c b\u1ea1n?<\/p>\n<p>Sau khi ChakraUI v\u00e0 React Hook Form \u0111\u00e3 \u0111\u1ee7 &quot;ch\u00edn&quot;, m\u00ecnh ti\u1ebfn h\u00e0nh chuy\u1ec3n \u0111\u1ed5i d\u1ef1 \u00e1n t\u1eeb AntDesign qua ChakraUI. Qu\u00e1 tr\u00ecnh n\u00e0y di\u1ec5n ra kh\u00e1 nhanh v\u00e0 su\u00f4n s\u1ebb, m\u1ed9t ph\u1ea7n v\u00ec \u0111\u00e3 c\u00f3 chu\u1ea9n b\u1ecb k\u1ef9 h\u01a1n l\u1ea7n tr\u01b0\u1edbc, m\u1ed9t ph\u1ea7n l\u00e0 v\u00ec l\u1ea7n n\u00e0y kh\u00f4ng c\u1ea7n ph\u1ea3i can thi\u1ec7p v\u00e0o c\u00e1c file service, utils, &#8230; \u0111\u1ec3 chuy\u1ec3n qua TypeScript n\u1eefa n\u00ean c\u00f4ng vi\u1ec7c ph\u1ea3i l\u00e0m gi\u1ea3m \u0111i \u0111\u00e1ng k\u1ec3.<\/p>\n<h2>Private package v\u1edbi Verdaccio<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2022\/02\/verdaccio-150x150.png\" alt=\"Verdaccio logo\" \/><\/p>\n<p>Sau khi \u0111\u00e1nh gi\u00e1 v\u00e0 &quot;ch\u1ed1t \u0111\u01a1n&quot; combo ChakraUI v\u00e0 React Hook Form th\u00ec m\u00ecnh c\u00f3 th\u1ea3o lu\u1eadn v\u1edbi team v\u1ec1 vi\u1ec7c \u00e1p d\u1ee5ng combo n\u00e0y cho c\u00e1c d\u1ef1 \u00e1n kh\u00e1c n\u1eefa. T\u1ea5t nhi\u00ean l\u00e0 team \u0111\u1ed3ng \u00fd l\u00e0m r\u1ed3i, nh\u01b0ng team kh\u00f4ng mu\u1ed1n vi\u1ec7c ph\u1ea3i copy v\u00e0 paste code t\u1eeb d\u1ef1 \u00e1n n\u00e0y qua d\u1ef1 \u00e1n kh\u00e1c. H\u01a1n n\u1eefa, m\u1ed7i l\u1ea7n c\u00f3 thay \u0111\u1ed5i l\u1ea1i ph\u1ea3i l\u1eb7p l\u1ea1i qu\u00e1 tr\u00ecnh \u0111\u1ea5y m\u1ed9t l\u1ea7n n\u1eefa. R\u1ee7i m\u00e0 qu\u00ean n\u00f3i nhau th\u00ec giao di\u1ec7n m\u1ed7i ng\u01b0\u1eddi m\u1ed9t ki\u1ec3u lu\u00f4n.<\/p>\n<p>Nh\u1eadn ra v\u1ea5n \u0111\u1ec1 th\u00ec m\u00ecnh b\u1eaft \u0111\u1ea7u t\u00ecm hi\u1ec3u v\u1ec1 c\u00e1ch \u0111\u0103ng t\u1ea3i (publish) m\u1ed9t package ri\u00eang cho team s\u1eed d\u1ee5ng. V\u00ec d\u1ef1 ki\u1ebfn package n\u00e0y ch\u1ec9 l\u01b0u h\u00e0nh n\u1ed9i b\u1ed9 n\u00ean m\u00ecnh \u01b0u ti\u00ean private package h\u01a1n l\u00e0 public. T\u1ea5t nhi\u00ean l\u00e0 ngo\u00e0i vi\u1ec7c t\u1ea1o package th\u00ec v\u1eabn c\u00f3 c\u00e1c d\u1ecbch v\u1ee5 kh\u00e1c h\u1ed7 tr\u1ee3 share code nh\u01b0ng chi ph\u00ed qu\u00e1 cao ho\u1eb7c c\u00e1ch thi\u1ebft l\u1eadp qu\u00e1 ph\u1ee9c t\u1ea1p khi\u1ebfn m\u00ecnh b\u1ecf qua c\u00e1c gi\u1ea3i ph\u00e1p \u0111\u1ea5y.<\/p>\n<p>T\u00ecm hi\u1ec3u kho\u1ea3ng m\u1ed9t ng\u00e0y th\u00ec m\u00ecnh ch\u1ecdn ra \u0111\u01b0\u1ee3c hai gi\u1ea3i ph\u00e1p sau:<\/p>\n<ul>\n<li><strong>NPM private package<\/strong>. Private package \u0111\u01b0\u1ee3c h\u1ed7 tr\u1ee3 s\u1eb5n b\u1edfi NPM. \u0110\u01a1n gi\u1ea3n, d\u1ec5 d\u00f9ng, kh\u00f4ng c\u1ea7n thi\u1ebft l\u1eadp g\u00ec nhi\u1ec1u. Tuy nhi\u00ean th\u00ec chi ph\u00ed s\u1eed d\u1ee5ng kh\u00e1 cao so v\u1edbi team. Gi\u00e1 t\u1ea1i th\u1eddi \u0111i\u1ec3m \u0111\u00f3 l\u00e0 $7 cho m\u1ed9t th\u00e0nh vi\u00ean. N\u1ebfu <del>keo ki\u1ec7t<\/del> ti\u1ebft ki\u1ec7m ch\u1ec9 c\u1ea5p t\u00e0i kho\u1ea3n cho leader d\u00f9ng th\u00ec c\u0169ng m\u1ea5t $7 x 2 = $14 cho m\u1ed9t th\u00e1ng r\u1ed3i<\/li>\n<li><strong>Verdaccio<\/strong>. \u0110\u00e2y l\u00e0 m\u1ed9t gi\u1ea3i ph\u00e1p private package t\u1ef1 host, t\u00edch h\u1ee3p \u0111\u01b0\u1ee3c v\u1edbi NPM. T\u00ecm hi\u1ec3u s\u00e2u h\u01a1n th\u00ec Verdaccio c\u00f3 nh\u1eefng gi\u1edbi h\u1ea1n nh\u1ea5t \u0111\u1ecbnh so v\u1edbi NPM &quot;x\u1ecbn&quot; nh\u01b0ng v\u1ec1 l\u00fd thuy\u1ebft th\u00ec v\u1eabn \u0111\u00e1p \u1ee9ng \u0111\u1ee7 nhu c\u1ea7u cho team. H\u01a1n n\u1eefa, \u0111\u1ec3 t\u1ef1 host Verdaccio th\u00ec kh\u00f4ng c\u1ea7n t\u1ed1n qu\u00e1 nhi\u1ec1u, ch\u1ec9 c\u1ea7n m\u1ed9t c\u1ee5m VPS gi\u00e1 $5 l\u00e0 \u0111\u00e3 c\u00f3 th\u1ec3 ch\u1ea1y ngon l\u00e0nh r\u1ed3i<\/li>\n<\/ul>\n<p>N\u00f3i \u0111\u1ebfn \u0111\u00e2y ch\u1eafc c\u00e1c b\u1ea1n c\u0169ng \u0111o\u00e1n \u0111\u01b0\u1ee3c team ch\u1ecdn gi\u1ea3i ph\u00e1p n\u00e0o r\u1ed3i nh\u1ec9. Trong l\u00fac ch\u1edd team backend tri\u1ec3n khai Verdaccio th\u00ec m\u00ecnh t\u00ecm hi\u1ec3u v\u1ec1 c\u00e1ch t\u1ea1o m\u1ed9t package nh\u01b0 th\u1ebf n\u00e0o. Package n\u00e0y ch\u1ee7 y\u1ebfu s\u1ebd b\u1ed5 sung c\u00e1c component c\u00f2n thi\u1ebfu c\u1ee7a ChakraUI, v\u00ed d\u1ee5 nh\u01b0 DatePicker, ColorPicker, Rich-text Editor, &#8230; \u0111\u1ed3ng th\u1eddi t\u1ea1o khung giao di\u1ec7n (layout) th\u01b0\u1eddng s\u1eed d\u1ee5ng \u0111\u1ec3 dev kh\u00f4ng c\u1ea7n ph\u1ea3i t\u1ea1o l\u1ea1i n\u1eefa. \u0110i\u1ec1u n\u00e0y v\u1eeba ti\u1ebft ki\u1ec7m th\u1eddi gian ph\u00e1t tri\u1ec3n, v\u1eeba gi\u00fap \u0111\u1ed3ng b\u1ed9 giao di\u1ec7n gi\u1eefa c\u00e1c d\u1ef1 \u00e1n v\u1edbi nhau. \u0110\u00e2y c\u0169ng l\u00e0 m\u1ed9t trong nh\u1eefng \u1ea5p \u1ee7 c\u1ee7a anh ch\u1ecb em trong team b\u1ea5y l\u00e2u nay, b\u00e2y gi\u1edd m\u1edbi c\u00f3 c\u01a1 h\u1ed9i bi\u1ebfn n\u00f3 th\u00e0nh hi\u1ec7n th\u1ef1c.<\/p>\n<h2>C\u00f4ng ngh\u1ec7 b\u1ed5 tr\u1ee3<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2022\/02\/prettier-logo-150x150.png\" alt=\"Prettier logo\" \/> <img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2022\/02\/eslint-logo-150x150.png\" alt=\"ESLint logo\" \/><\/p>\n<p>Ngo\u00e0i vi\u1ec7c thay \u0111\u1ed5i c\u00e1c c\u00f4ng ngh\u1ec7 ch\u00ednh \u0111\u1ec3 x\u00e2y d\u1ef1ng d\u1ef1 \u00e1n th\u00ec m\u00ecnh c\u0169ng mu\u1ed1n t\u00edch h\u1ee3p c\u00e1c c\u00f4ng ngh\u1ec7 b\u1ed5 tr\u1ee3 cho qu\u00e1 tr\u00ecnh ph\u00e1t tri\u1ec3n c\u1ee7a team, c\u1ee5 th\u1ec3:<\/p>\n<ul>\n<li><strong>Husky<\/strong>. Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3 ch\u1ea1y l\u1ec7nh th\u00f4ng qua <em>git hook<\/em> (commit, push, &#8230;). M\u00ecnh d\u00f9ng \u0111\u1ec3 trigger c\u00e1c l\u1ec7nh c\u1ea7n thi\u1ebft \u0111\u1ec3 ki\u1ec3m tra ch\u1ea5t l\u01b0\u1ee3ng code c\u0169ng nh\u01b0 \u0111\u1ea3m b\u1ea3o r\u1eb1ng kh\u00f4ng c\u00f3 l\u1ed7i ho\u1eb7c \u00edt l\u1ed7i x\u1ea3y ra khi tri\u1ec3n khai l\u00ean m\u00f4i tr\u01b0\u1eddng production<\/li>\n<li><strong>Lint-staged<\/strong>. Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3 ch\u1ea1y l\u1ec7nh cho c\u00e1c file \u0111\u01b0\u1ee3c staged (d\u00f9ng l\u1ec7nh <code>git add<\/code>). M\u00ecnh d\u00f9ng \u0111\u1ec3 ch\u1ea1y ESLint \u0111\u1ec3 check l\u1ed7i v\u00e0 Prettier \u0111\u1ec3 format l\u1ea1i code<\/li>\n<li><strong>ESLint<\/strong>. Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3 ki\u1ec3m tra l\u1ed7i c\u0169ng nh\u01b0 c\u00e1c best practice n\u00ean c\u00f3 trong d\u1ef1 \u00e1n. Nh\u1eefng l\u1ed7i ng\u1edb ng\u1ea9n nh\u01b0 g\u00f5 sai t\u00ean bi\u1ebfn, tr\u00f9ng t\u00ean bi\u1ebfn ho\u1eb7c khai b\u00e1o thi\u1ebfu dependencies (bi\u1ebfn ph\u1ee5 thu\u1ed9c) khi s\u1eed d\u1ee5ng hook \u0111\u1ec1u \u0111\u01b0\u1ee3c &quot;b\u1eaft&quot; v\u00e0 ng\u0103n ch\u1eb7n k\u1ecbp th\u1eddi tr\u01b0\u1edbc khi commit<\/li>\n<li><strong>Prettier<\/strong>. Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3 format code. Theo m\u00ecnh quan s\u00e1t th\u00ec ki\u1ec3u c\u00e1ch (style) code m\u1ed7i ng\u01b0\u1eddi s\u1ebd kh\u00e1c nhau. Khi commit th\u00ec xu\u1ea5t hi\u1ec7n nhi\u1ec1u style trong m\u1ed9t file khi\u1ebfn vi\u1ec7c \u0111\u1ecdc code \u0111\u00f4i l\u00fac h\u01a1i kh\u00f3 kh\u0103n. M\u00ecnh thi\u1ebft l\u1eadp prettier \u0111\u1ec3 gi\u1ea3i quy\u1ebft v\u1ea5n \u0111\u1ec1 n\u00e0y. Khi code dev c\u00f3 th\u1ec3 format theo s\u1edf th\u00edch c\u00e1 nh\u00e2n c\u1ee7a m\u00ecnh nh\u01b0ng khi commit th\u00ec code s\u1ebd \u0111\u01b0\u1ee3c format v\u1ec1 m\u1ed9t \u0111\u1ecbnh d\u1ea1ng chung, t\u1ea1o s\u1ef1 \u0111\u1ed3ng nh\u1ea5t gi\u1eefa c\u00e1c th\u00e0nh vi\u00ean trong team<\/li>\n<\/ul>\n<p>M\u1eb7c d\u00f9 \u0111\u00f4i l\u00fac c\u00f3 h\u01a1i kh\u00f3 ch\u1ecbu khi c\u1ea7n s\u1eeda l\u1ed7i g\u1ea5p m\u00e0 v\u1eabn ph\u1ea3i ch\u1edd ki\u1ec3m tra nh\u01b0ng c\u0169ng nh\u1edd v\u1eady m\u00e0 gi\u1ea3m \u0111i \u0111\u00e1ng k\u1ec3 s\u1ed1 l\u1ea7n ph\u1ea3i s\u1eeda \u0111i s\u1eeda l\u1ea1i l\u1ed7i tr\u00ean production. Kh\u00e1ch h\u00e0ng c\u1ee7a EGANY c\u0169ng h\u00e0i l\u00f2ng h\u01a1n v\u1ec1 \u0111i\u1ec1u n\u00e0y.<\/p>\n<h2>T\u1ea1m k\u1ebft<\/h2>\n<p>Ch\u1eb7ng \u0111\u01b0\u1eddng chuy\u1ec3n \u0111\u1ed5i t\u1edbi \u0111\u00e2y l\u00e0 k\u1ebft th\u00fac. T\u1ea5t nhi\u00ean l\u00e0 c\u00f2n nhi\u1ec1u thay \u0111\u1ed5i kh\u00e1c n\u1eefa trong qu\u00e1 tr\u00ecnh th\u1ef1c hi\u1ec7n nh\u01b0ng kh\u00f3 l\u00f2ng n\u00e0o <del>nh\u1edb h\u1ebft \u0111\u01b0\u1ee3c<\/del> g\u00f3i g\u1ecdn \u0111\u01b0\u1ee3c trong m\u1ed9t b\u00e0i blog n\u00ean xin ph\u00e9p b\u1ecf qua nha m\u1ecdi ng\u01b0\u1eddi.<\/p>\n<p>B\u1ea3n th\u00e2n m\u00ecnh v\u00e0 team \u0111\u1ea1t \u0111\u01b0\u1ee3c kh\u00e1 nhi\u1ec1u th\u00e0nh qu\u1ea3 qua l\u1ea7n chuy\u1ec3n \u0111\u1ed5i n\u00e0y:<\/p>\n<ul>\n<li>Gi\u1ea3i quy\u1ebft v\u1ea5n \u0111\u1ec1 v\u1ec1 gi\u1ea5y ph\u00e9p<\/li>\n<li>Ti\u1ebfp x\u00fac nhi\u1ec1u c\u00f4ng ngh\u1ec7 m\u1edbi<\/li>\n<li>Bi\u1ebft c\u00e1ch th\u1eed nghi\u1ec7m, \u00e1p d\u1ee5ng c\u00f4ng ngh\u1ec7 sao cho hi\u1ec7u qu\u1ea3 nh\u1ea5t<\/li>\n<li>C\u00f3 \u0111\u01b0\u1ee3c package ch\u00ednh th\u1ee9c \u0111\u1ea7u ti\u00ean t\u1ea1i EGANY<\/li>\n<li>C\u00f3 khung s\u01b0\u1eddn d\u1ef1ng app ch\u1ec9nh chu, chuy\u00ean nghi\u1ec7p<\/li>\n<li>R\u00fat ng\u1eafn th\u1eddi gian tri\u1ec3n khai d\u1ef1 \u00e1n m\u1edbi<\/li>\n<li>M\u1ed9t ch\u00fat &quot;danh v\u1ecdng&quot; khi tham gia h\u1ed7 tr\u1ee3 th\u01b0 vi\u1ec7n React Hook Form<\/li>\n<li><del>N\u1ed9i dung \u0111\u1ec3 vi\u1ebft blog<\/del><\/li>\n<\/ul>\n<p>Hi v\u1ecdng b\u00e0i vi\u1ebft s\u1ebd gi\u00fap \u00edch \u0111\u01b0\u1ee3c cho c\u00e1c b\u1ea1n \u0111\u00e3, \u0111ang v\u00e0 s\u1ebd tri\u1ec3n khai m\u1ed9t d\u1ef1 \u00e1n t\u01b0\u01a1ng t\u1ef1 nh\u01b0 CPA. N\u1ebfu kh\u00f4ng gi\u00fap \u00edch \u0111\u01b0\u1ee3c c\u00e1c b\u1ea1n trong c\u00f4ng vi\u1ec7c th\u00ec hi v\u1ecdng b\u1ea1n \u0111\u00e3 c\u00f3 nh\u1eefng gi\u00e2y ph\u00fat \u0111\u1ecdc b\u00e0i th\u1eadt tho\u1ea3i m\u00e1i. N\u1ebfu c\u00f3 b\u1ea5t k\u1ef3 th\u1eafc m\u1eafc ho\u1eb7c g\u00f3p \u00fd n\u00e0o, c\u00e1c b\u1ea1n c\u1ee9 comment \u1edf b\u00ean d\u01b0\u1edbi nha.<\/p>\n<p>C\u00e1m \u01a1n c\u00e1c b\u1ea1n \u0111\u00e3 \u0111\u1ecdc b\u00e0i. Happy hacking!<\/p>\n<blockquote>\n<p>N\u1ebfu b\u1ea1n th\u1ea5y h\u00e0nh tr\u00ecnh b\u1ecdn m\u00ecnh th\u00fa v\u1ecb v\u00e0 mu\u1ed1n c\u00f9ng nhau vi\u1ebft ti\u1ebfp th\u00ec <a href=\"https:\/\/egany.com\/blogs\/front-end-engineer-reactjs-nextjs-typescript-svelte\/\" title=\"tham kh\u1ea3o th\u00f4ng tin n\u00e0y\">tham kh\u1ea3o th\u00f4ng tin n\u00e0y<\/a> nh\u00e9 \ud83d\ude03<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>C\u1eafm \u0111\u1ea7u c\u1eafm c\u1ed5 d\u1ecdn d\u1eb9p deadline v\u00e0 d\u1ecdn nh\u00e0 tr\u01b0\u1edbc T\u1ebft n\u00ean ng\u00e2m b\u00e0i blog l\u00ean men lu\u00f4n r\u1ed3i. Xin l\u1ed7i m\u1ecdi ng\u01b0\u1eddi nh\u00e9. Nay r\u1ea3nh r\u1ed7i c\u00f3 ch\u00fat th\u1eddi gian tranh th\u1ee7 vi\u1ebft l\u00e1ch m\u1ed9t t\u00ed k\u1ebbo s\u1ebfp bi\u1ebft l\u1ea1i giao th\u00eam task. N\u1ebfu b\u1ea1n ch\u01b0a \u0111\u1ecdc t\u1eadp tr\u01b0\u1edbc, b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecdc t\u1ea1i \u0111\u00e2y. Gi\u1edbi thi\u1ec7u Cross-platform Apps s\u1ebd \u0111\u01b0\u1ee3c vi\u1ebft t\u1eaft b\u1eb1ng CPA \u0111\u1ec3 thu\u1eadn ti\u1ec7n cho ng\u01b0\u1eddi vi\u1ebft b\u00e0i Sau khi nh\u1eadn ra v\u1ea5n \u0111\u1ec1 v\u1ec1 license (t\u1ea1m d\u1ecbch l\u00e0 gi\u1ea5y ph\u00e9p s\u1eed d\u1ee5ng) li\u00ean quan t\u1edbi Shopify Polaris, team quy\u1ebft \u0111\u1ecbnh t\u1ea1m th\u1eddi ng\u1eebng<\/p>\n","protected":false},"author":2,"featured_media":1171,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[27,1],"tags":[142,137,138,87,90,140,141,32,144,139,143,64,37],"_links":{"self":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/posts\/1155"}],"collection":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/comments?post=1155"}],"version-history":[{"count":0,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/posts\/1155\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/media\/1171"}],"wp:attachment":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/media?parent=1155"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/categories?post=1155"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/tags?post=1155"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}