-->
ads here

Breaking React into Fragments

advertise here
Xin chào các bạn hôm nay chúng ta sẽ có 1 bài viết để giải quyết 1 vấn đề hay gặp phải khi code Front end sử dụng ReactJS và cách giải quyết chúng bằng cách sử dụng React Fragment.
Bài viết của chúng ta sẽ gồm 2 phần:
  1. Giới thiệu vấn đề
  2. Hướng giải quyết: Fragment
OK, Let's begin!

1. Giới thiệu vấn đề:

Chắc hẳn khi lập trình với React bạn sẽ gặp trường hợp phải tạo ra những component thế này 

 const Component1 = () => {  
      return (  
           <div>Hello</div>  
           <div>Hello2</div>  
      )  
 }  
 const Component2 = () => {  
      return (  
           <Component1 />  
           <Component1 />  
      )  
 }  

Khi đó bạn sẽ nhận được warning như sau nếu dùng 1 số editor có hỗ trợ JSX extension:
JSX parent expressions must have one parent element
Hoặc khi build thì bạn sẽ nhận được lỗi sau:

SyntaxError: unknown: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?
 Để giải quyết vấn đề này, thông thường chúng ta hay thêm tag div để bao lại component của chúng ta để hàm render chỉ return về 1 element duy nhất.

 const Component1 = () => {  
      return (  
       <div>  
        <div>Hello</div>  
        <div>Hello2</div>  
       </div>  
      )  
 }  
 const Component2 = () => {  
      return (  
       <div>  
         <Component1 />  
         <Component1 />  
       </div>  
      )  
 }  

Khi đó, vấn đề lại xuất hiện bởi vì tag div này. Trong một số trường hợp tag div có thể gây vỡ cấu trúc DOM, điển hình là khi ta render một table có cấu trúc như sau:

 <table>  
  <tr>  
   <th>Firstname</th>  
   <th>Lastname</th>   
   <th>Age</th>  
  </tr>  
  <tr>  
   <td>Jill</td>  
   <td>Smith</td>   
   <td>50</td>  
  </tr>  
 </table>  

Ta sẽ hiện thực table này trong React như sau:

 const Table = () => {  
      return (  
       <table>  
        <tr>  
         <TableHeader />  
        </tr>  
        <tr>  
         <TableBody />  
        </tr>  
       </table>  
      )  
 }  
 const TableHeader = () => {  
      return (  
       <th>Firstname</th>  
       <th>Lastname</th>  
       <th>Age</>  
      )  
 }  
 cont TableBoby = () => {  
      return (  
       <td>Jill</td>  
       <td>Smith</td>   
       <td>50</td>  
      )  
 }  

Và lúc này vấn đề như đã nó ở trên xuất hiện, <TableHeader /> và <TableBody> trả về nhiều HTML node, nên khi đó React yêu cầu mỗi Component chỉ return 1 Node mà thôi, khi đó chúng ta phải thêm div vào để xử lý vấn đề này

 const TableHeader = () => {  
      return (  
       <div>  
        <th>Firstname</th>  
        <th>Lastname</th>  
        <th>Age</>  
       </div>  
      )  
 }  
 cont TableBoby = () => {  
      return (  
       <div>  
        <td>Jill</td>  
        <td>Smith</td>   
        <td>50</td>  
       </div>  
      )  
 }  

Lúc này vấn đề nhiều node đã được giải quyết, tuy nhiên khi đó chúng ta lại gặp phải vấn đề là cấu trúc của table đã thay đổi làm sai kết quả khi hiển thị trên trình duyệt

<table>  
  <tr>  
       <div>  
         <th>Firstname</th>  
         <th>Lastname</th>   
         <th>Age</th>  
       </div>  
  </tr>  
  <tr>  
       <div>  
         <td>Jill</td>  
         <td>Smith</td>  
         <td>50</td>  
       </div>  
  </tr>  
 </table>  

Tag div sẽ làm sai lệch đi cấu trúc DOM. React component cho phép return nhiều element được enclose trong 1 parent tag, nếu return nhiều element thì sẽ không cho phép. Nhưng nếu thêm div vào thì có khả năng gây sai kết quả của DOM. Vậy chúng ta giải quyết vấn đề này như thế nào?

Câu trả lời chính là React.Fragment

2. Hướng giải quyết: Fragments

Theo trang chủ của React, Fragments cho phép nhóm nhiều element con mà không cần thiết phải thêm node vào cấu trúc DOM 
Fragments let you group a list of children without adding extra nodes to the DOM.
Bằng cách sử dụng <React.Fragment>...</React.Fragment>, ta có thể thêm parent tag vào JSX element mà không cần thêm bất kì HTML node nào vào DOM cả. Fragment cho phép nhóm các element vào trong 1 parent tag nhưng không hề có HTML node nào được thêm vào, và điều đó giải quyết được toàn bộ vấn để được đặt ra ở trên. Bây giờ chúng ta hãy thử apply React.Fragment vào các Component ở mục 1.

Component 1:

 const Component1 = () => {   
    return (   
     <React.Fragment>   
        <div>Hello</div>   
        <div>Hello2</div>   
     </React.Fragment>   
    )   
  }   

Component 2:

 const Component2 = () => {   
    return (   
     <React.Fragment>   
        <Component1 />   
        <Component1 />   
     </React.Fragment>   
    )   
  }  

TableHeader:

 const TableHeader = () => {  
      return (  
       <React.Fragment>  
          <th>Firstname</th>  
          <th>Lastname</th>  
          <th>Age</>  
       </React.Fragment>  
      )  
 }  

TableBody:

cont TableBoby = () => {  
      return (  
       <React.Fragment>  
         <td>Jill</td>  
         <td>Smith</td>   
         <td>50</td>  
       </React.Fragment>  
      )  
 }  

Khi đó,  cấu trúc DOM của table sẽ trở nên như ta mong muốn, không có tag div nào được thêm vào cả.
Ngoài ra, thay vì viết <React.Fragment>...</React.Fragment> ta có thể viết ngắn gọn hơn bằng cách <>...</> như sau:

cont TableBoby = () => {  
      return (  
       <>  
         <td>Jill</td>  
         <td>Smith</td>   
         <td>50</td>  
       </>  
      )  
 }  

Kết

Bài viết này giúp ta thấy được vấn đề của React khi return nhiều hơn 1 element và biết cách sử dụng React Fragment để giải quyết vấn đề này. Với React.Fragment, chúng ta có thể thoải mái trả về nhiều hơn 1 element trong mỗi component của React mà không cần phải thêm bất khì tag nào để wrap nó lại, đồng thời không lo ảnh hưởng để cấu trúc DOM.
Hi vọng bài viết này có thể giúp ích được cho các bạn trong quá trình sử dụng React trong công việc của mình. Nếu thấy hay hay chia sẻ cho mọi người cùng biết, nếu có ý kiến đóng góp đừng ngần ngại để lại comment cho mình ở phía dưới bài viết nhé. Xin cảm ơn!

Referrence:


Advertisement
COMMENTS ()