iT邦幫忙

2023 iThome 鐵人賽

DAY 5
1
Modern Web

30天React練功坊-攻克常見實務/面試問題系列 第 5

30天React練功坊-攻克常見實務/面試問題 Day5 An unexpected "0" in the page while doing condition rendering

  • 分享至 

  • xImage
  •  
tags: ItIron2023 react

前言

昨天我們談到了多個類似的state在同一組件的管理問題,以及你可以如何利用一個共用的hanlder去優化,今天我們換個主題,把重點先從useState抽開換換口味。
條件渲染是一個你幾乎在實務中無法避免的東西,由於條件渲染搞出的狀態自然也是層出不窮,今天要看的同樣是一個不算罕見的情況,我自己在第一份工作時就有不小心犯過這個錯誤,馬上來看一下吧!

本日題目

請一樣先看一下這個codesandbox,題目是個很單純的條件渲染,我們有個friends陣列用來展示該使用者的所有朋友,並想在陣列長度為0的情況下渲染出其他的訊息,同時我們有個setTimeout去模擬請求資料的行為,在收到資料前陣列為空。

day5-image-code

最終畫面雖然如我們預期的變動成展示完整的朋友名單,但在取得資料前卻有個奇怪的0出現在頁面上,請試著修復這個問題。

day5-demo-gif

export default function App() {
  const [friends, setFriends] = useState([]);

  useEffect(() => {
    // use a timeout to simulate fetch request
    setTimeout(() => {
      setFriends(DEFAULT_LIST_FOR_DEMO);
    }, 1500);
  }, []);
  return (
    <div className="App">
      <h1>An unexpected "0" in the page while doing conditional rendering</h1>
      {friends.length && (
        <div>
          {friends.map((friend) => (
            <div key={friend.id}>This is your friend, {friend.name}</div>
          ))}
        </div>
      )}
      {!friends.length && <p>I am sorry, you have no friends</p>}
    </div>
  );
}

解答與基本解釋

這類的情況往往出現在條件渲染時,尤其是陣列的情況為多,原因在於許多人會利用像是array.length這樣的條件判斷是否該渲染某些元素,畢竟我們在寫js條件式的時候就很喜歡善用(濫用)js的自動轉型機制,很多時候我們會寫出類似這樣的條件

if (arr.length) {
    // do something
}

接著就不小心把這樣的思維帶到react中了,雖然0、null、undefined之類的falsy value會因為自動轉型的關係讓你條件式如你所想運作,但在渲染時就不完全是這麼一回事了。
舉個例子來說,你在傳統的html寫了類似這樣的東西,你也不會期待0就這樣消失,他還是一個很單純的元素,並不是因為falsy value它就不渲染。

<h1>0</h1>

至於為什麼null & false這樣的值也不會被渲染,那就跟react的機制有關係了,react將null & false視為 no-rendering,因此這類的值並不會在畫面上出現,這個小巧思也給了我們彈性讓我們可以有效率的撰寫條件渲染。 理解這一點後我們來看一下程式碼,我想你就會瞭解了

{friends.length && (
  // some code here
)}

當左邊為0時,此時程式碼等價於

{0 && (
  // some code here
)}

而&&運算子的規則很簡單,若運算子左邊的值可以轉為true,此時回傳右手邊的值,反之回傳左手邊的值,舉幾個簡單的例子

1 && 2 => 2
1 && 0 => 0
0 && 1 => 0

因此在資料回傳前,長度為0的陣列經過上方的運算自然會回傳0,最終渲染在畫面上,理解這點後解決方法就很簡單了,有數種不同的方式你可以使用,但原則都是一樣的,不要用數字當條件渲染的值,比方說你可以用以下兩種寫法,都能解決你的問題!

{friends.length > 0 && (
  // some code here
)}

// or

{!!friends.length && (
  // some code here
)}

藉由讓運算子左邊變為布林值會是最好的做法,也可以避免更多類似的情況!

總結

我們今天快速看了一個新手常見的條件渲染錯誤,同時幫讀者複習了一下關於js運算子的一些小常識,相信理解原因後一切都沒有這麼莫名其妙了對吧? 條件渲染還會在陪我們一陣子,我們明天見囉!

參考資料

react conditional rendering

本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!


上一篇
30天React練功坊-攻克常見實務/面試問題 Day4: Way too many state in a component
下一篇
30天React練功坊-攻克常見實務/面試問題 Day6: Rendered more hooks than during the previous render.
系列文
30天React練功坊-攻克常見實務/面試問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
lijun
iT邦新手 4 級 ‧ 2023-12-06 14:38:20

作者您好
因為使用了setTimeout 所以畫面會在1.5s後才會setFriends
所以在這時候friends陣列裡並沒有值,所以當下方 &&運算子判斷的時候會回傳0在畫面上.
1.5s重新渲染後才會顯示值出來.

好像也能使用三元運算子:?的方式
一開始的時候friends陣列為0
0 在條件判斷時是false

      {friends.length ? (
        <div>
          {friends.map((friend) => (
            <div key={friend.id}>This is your friend, {friend.name}</div>
          ))}
        </div>
      ) : (
        <p>I am sorry, you have no friends</p>
      )}

理解錯了話請糾正我 感謝作者的好文

lijun 理解正確,三元運算也是在寫jsx經常運用到的技巧,以這個範例來說確實也是解決問題的方法之一!Good job! 唯一你需要注意的是每個團隊對於在jsx中用三元運算的規範,曾經有聽過有些團隊會為了可讀性而盡量避免這樣的寫法,但邏輯上是完全沒有問題的!

我要留言

立即登入留言