iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 16
1
Modern Web

I Want To Know React系列 第 16

I Want To Know React - Render list

React render list

使用情境

在撰寫前端頁面常常會需要把 list 中的內容全部顯示到畫面上。

舉例來說,我們可能會需要把一個 list(Array)的內容全部顯示在一個表格中,又或者需要把 list 的內容顯示成一個項目清單列表。

在這章節中,我們就要來學習如何使用 React render list 中的內容。

實作概念

React render list 與上一篇介紹的條件 render 一樣,沒有用到任何特殊的語法,它只是 JavaScript 與 JSX 的應用而已,只要熟悉初探 JSXJSX 語法章節的內容就可以快速精通了!但首先我們還是先來了解一下 render list 的實作概念吧!

React 要怎麼 render 出一個 list 中的所有內容呢?

先來看看 React component 的 render API 允許回傳哪些內容:

  • React Elements
  • Array & Fragments
  • Portals
  • String & numbers
  • Booleans or null

可以看到 Array 是一個合法的 render 回傳值,這代表 React 是支援直接 render list 的!

也就是說,只要把一個 list 傳給 React,它就會幫我們 render 出 list 中的全部元素。

開發者需要做的就只是應用 JSX 與 JavaScript 語法把 list 的元素加工成自己要的樣子(e.g. 把每個元素做成 React element)後傳給 React render 就好,舉例來說:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
  <li>{numbers}</li>
);

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);
// Warning: Each child in a list should have a unique 'key' prop.

讀者也可以到 CodePen 中實際操作看看。

範例中將一個 number 組成的 list(numbers),用 map 處理成 React element <li> list(listItems)。之後把 React element list 交給 React render,即可產出對應的 <li> 到畫面上。

使用須知:List 中的每個 React element 元素中應加上 key

需要注意的是,如果要 render 一個 React element list,則必須在 list 中的每個 React element 元素中都加上 key 才不會出現 warning。

回到上一個範例,可以發現因為 <li> 沒有加上 key 所以會噴出警告:Warning: Each child in a list should have a unique 'key' prop.

現在就來修掉這個警告吧:

const listItems = numbers.map((numbers) =>
  <li key={number}>{numbers}</li>
);
// won't have warning

讀者也可以到 CodePen 中查看 console。

可以發現只要為 <li> 加上 key 就不會出現剛剛的警告了。key 的詳細內容將會在下一章介紹。目前只要知道,key 的值要是 list 中的唯一值即可。

了解 React render list 的實作概念與使用須知後,就可以開始說明一些 render list 的常見技巧了。以下介紹的方法都是可行的 render list 處理方式,讀者視可讀性與當下情境選擇要使用哪種寫法即可。

用變數儲存 map 處理好的 list

第一種方式是把要 render 的 list 判斷好後存在變數中,並在 JSX Expression 中使用這個變數即可。

實作概念 段落的範例,假設我們有個需求是把 list 中內容全部顯示到一個項目清單中,則可以這樣實作:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
  <li key={number}>{numbers}</li>
);

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

讀者也可以到 CodePen 中實際操作看看。

只要把 numbers list 用 map 處理成 <li> 組成的 list,並存到變數中。接著我們就可以把這個變數放到 JSX expression 給 React render 出對應的項目清單到畫面上了。

在 expression 中用 map 處理 list

另一種處理 list 的技巧是在 expression 中直接用 map 處理 list。

使用這個方法試著修改項目清單的範例吧:

const numbers = [1, 2, 3, 4, 5];

ReactDOM.render(
  <ul>
    {numbers.map((number) => (
      <li key={number.toString()}>{number}</li>
    ))}
  </ul>,
  document.getElementById('root')
);

可以看到範例中,numbers.map 的邏輯處理直接被嵌入 JSX expression 中,而沒有額外在宣告一個變數去接 map 處理好的 React element list 了。

這樣寫的功能與上一個範例是完全相同的,差別只在於 coding style 而已。有時候將 map 邏輯直接寫在 expression 裡可以提升易讀性,有時反而降低易讀性,因此就視當下狀況決定要用哪個技巧吧!

進階應用

需要記住的是,上面兩個段落提到的 map 處理 list 只是技巧而已。Render list 的重點在於是否有把合法的 list 交給 React render,至於用怎麼樣的邏輯產出 list 則是 component 各自封裝的實作細節。有了這個概念後,就可以學習更靈活的應用 React render list 了!

讓我們來定義一下何謂 合法的 list

實作概念 段落提到,Array 是 React 可以 render 的型別。那 React 對於 Array 內的元素有型別有限制嗎?

回想一下 React render 可以支援的型別吧:

  • React Elements
  • Array & Fragments
  • Portals
  • String & numbers
  • Booleans or null

那讀者們有猜到 Array 內的元素需要是哪些型別才可以正常的讓 React render 了嗎?

沒錯,Array 內的元素只要是以上提到的五種型別就會是個可被 render 的合法 list 了。

也就是說:

  • render 的 Array 中可以包含 React Element
  • render 的 Array 中可以包含 Array
  • render 的 Array 中可以包含 Portals
  • render 的 Array 中可以包含 String & Number
  • render 的 Array 中可以包含 Booleans or null

來寫個範例測試看看吧:

const ReactElementList = (props) => (
  <div>
    <h2>Render React element list</h2>
    {[
      <li key={1}>1</li>,
      <li key={2}>2</li>,
      <li key={3}>3</li>,
      <li key={4}>4</li>,
      <li key={5}>5</li>
    ]}
  </div>
);

const StringList = (props) => (
  <div>
    <h2>Render String list</h2>
    {["test", "render", "array", "list"]}
  </div>
);

const NumberList = (props) => (
  <div>
    <h2>Render Number list</h2>
    {[1, 2, 3]}
  </div>
);

const ArrayList = (props) => (
  <div>
    <h2>Render Array list</h2>
    {[
      [1, 2, 3],
      ["test", "render", "array", "list"]
    ]}
  </div>
);

const BooleanAndNullList = (props) => (
  <div>
    <h2>Render Boolean And Null list</h2>
    {[true, false, null]}
  </div>
);

const MixedList = (props) => (
  <div>
    <h2>Render Array list</h2>
    {[<li key={1}>1</li>, "test", 1, ["array", "list"], true, false, null]}
  </div>
);

ReactDOM.render(
  <div>
    <ReactElementList />
    <StringList />
    <NumberList />
    <ArrayList />
    <BooleanAndNullList />,
    <MixedList />
  </div>,
  document.getElementById("root")
);

讀者可以到 CodePen 上查看結果。

範例中 render 了各個型別的 list,包括 ReactElementListStringListNumberListArrayListBooleanAndNullList,最後甚至還 render 了內含各種不同型別元素的 MixedList

因此可以證明,只要是 React 可以 render 的型別,就可以作為 render 的 list(Array)的元素。就算是 list 中混雜著各種類型的可 render 型別也是完全合法的。

在實際專案中也許用不到像是 render Array 中的 Array 這種極端的狀況,但相信通過此練習,讀者可以更深入的理解 render list 的概念,而不會卡在一定要把 list 的所有元素都轉成 React element 才能 render 的思維裡。

小結

在此章節中,我們學習了 React render list 的概念。

因為 React 可以支援 render Array 型別,因此開發者只要把要放到畫面上的 list 傳給 React 即可。

另外,React 可以 render 型別都可以作為 Array 的元素,包括:

  • React Elements
  • Array & Fragments
  • Portals
  • String & numbers
  • Booleans or null

最後,我們可以用以下的技巧將 React element list 傳給 React render:

  • 用變數儲存 map 處理好的 list
  • 在 expression 中用 map 處理 list

參考資料


上一篇
I Want To Know React - 條件 render
下一篇
I Want To Know React - 初探 Key
系列文
I Want To Know React30

尚未有邦友留言

立即登入留言