iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
自我挑戰組

SPYxFRONTEND ~ 懂一點後端真是讓人哇哭哇哭系列 第 16

[Day16] call API 會用的參數系列~用 filter 來限制條件吧!

  • 分享至 

  • xImage
  •  

本日正文

前幾天講了 axios 的 CRUD,
還有昨天講了 routes,
今天回過頭來講 filter 吧。

相信大家對網址列含有 ?& 的符號並不陌生,
像是鐵人賽的個人頁面網址就長這樣:
https://ithelp.ithome.com.tw/users/20129873/ironman/5274?page=1

?page=1 其實就是前端 call API 時給它的 filter 哦,
?page=1 就代表前端只要求 API 回傳第1頁的資料就好,
以此類推,如果只要第2頁的資料,那麼我們參數就改成 ?page=2
那我們簡單試試看吧!
https://ithelp.ithome.com.tw/upload/images/20220917/201298733r7uN6KyEK.png

當然通常使用者不會自己去改瀏覽器網址列的參數,
而是透過使用者行為(EX. 輸入文字框、按下按鈕...)之後,
去改變前端 call API 的參數,
讓回傳的資料有所改變。

在 call API url 中用 ? 來限制條件

例如這邊我們簡單寫一個例子,
增加一個按鈕:

<Button mx={2} onClick={searchData} colorScheme="teal">搜尋資料</Button>

然後在 searchData 我們這樣寫:

function searchData(){
    axios.get(`${hostUrl}/api/v1/posts?author=Misado`)
      .then(function (response) {
          setdataResult(response.data);
          setDataFetchTimes(dataFetchTimes+1);
      })
      .catch(function (error) {
          alert("抓取資料錯誤,請確認後再試");
          console.log(error);
      })
  }

重點就是我們在原本 url /api/v1/posts 的地方,
後面加了 filter 條件 ?author=Misado
那我們來試試看效果:

原本有7筆資料,
但按下搜尋資料的按鈕之後,
就只回傳 author=Misado 的2筆資料。

若有多個限制條件:用 & 來連接

那如果現在我有多個條件呢?
例如現在我再多個條件只要拿編號為7,
該怎麼寫?

那就用 & 符號將兩個串接就好,
像這樣:

axios.get(`${hostUrl}/api/v1/posts?author=Misado&id=7`)

現在同時符合兩個條件的只有一筆資料:
https://ithelp.ithome.com.tw/upload/images/20220917/20129873haTaD30mRI.png

你也可以先在瀏覽器輸入 http://localhost:10000/api/v1/posts?author=Misado&id=7
https://ithelp.ithome.com.tw/upload/images/20220917/20129873wbTbvUvMsA.png
其實你會發現結果是一樣的,
所以通常在寫 filter 時,
我會自己先在瀏覽器的網址試試看,
確定這是我要的 filter 條件,
才把它正式寫到 function 去。

(PS. API 通常會寫 filter 但不一定都會寫,
這次我們自己起的 JSON Server 是都有支援,
但如果你發現前端想下的條件 API 並沒有吐相對的資料給前端的話,
可能就是 API 沒有寫這樣的邏輯,
這時候前端就要跟後端講說請把這個條件加進去)

同場加映:將之前的例子用 call API 改寫看看吧!

但如果今天的文章這樣就結束了好像有點無聊,
還記得之前的鐵人餐廳例子嗎?
之前我們是寫死資料,
但現在我們終於有 API 了,
所以就來改寫看看吧!

首先我們在 db.json 新增這樣的資料:

"sales": [
    {
      "item": "牛肉麵",
      "count": 66
    },
    {
      "item": "小籠包",
      "count": 55
    },
    {
      "item": "滷肉飯",
      "count": 30
    },
    {
      "item": "蚵仔麵線",
      "count": 25
    },
    {
      "item": "蚵仔煎",
      "count": 20
    }
  ]

(PS. 這邊讓我先把原本的 品項數量 改成英文的 itemcount
不然 url 會有中文編碼的問題,
那又是另外一件事了XD 有機會再說明~)

再來我們一樣先在瀏覽器試試看:

http://localhost:10000/api/v1/sales
https://ithelp.ithome.com.tw/upload/images/20220917/2012987331MlZf7mGz.png

確定 API 能夠正常回傳資料後我們就來進行改寫,

const [sales, setSales] = useState([]);
... (略)
function fetchData(){
      axios.get(`${hostUrl}/api/v1/sales`)
      .then(function (response) {
          console.log(response);
          setSales(response.data);
      })
      .catch(function (error) {
          alert("抓取資料錯誤,請確認後再試");
          console.log(error);
      })
  }

然後把第6天寫的前端 code 貼過來,
sales.map 的地方加個 ?
避免沒有資料就渲染導致錯誤,
像這樣:
https://codesandbox.io/s/2022day6-chakra-ui-k9eohm?file=/src/App.jsx:206-254

<Text my={4} as="h2" fontSize="2xl" textAlign="center">
  {today.getFullYear()} 鐵人餐廳 {today.getMonth() + 1}月 銷售排行 TOP5
</Text>
<OrderedList px={4}>
  {sales?.map((x) => (
	<ListItem my={2}>
	  <Flex>
		<Text>{x.item}</Text>
		{x.count >= hitCount ? (
		  <Tag ml={2} size="sm" variant="solid" colorScheme="red">
			人氣料理
		  </Tag>
		) : null}
	  </Flex>
	  <Text>銷售量:{x.count}</Text>
	</ListItem>
  ))}
</OrderedList>

然後來看看效果如何:

然後一樣複習一下剛剛介紹的 filter,
如果現在我們只想看銷售量(count)大於 hitCount 的資料該怎麼做呢?

JSON Server 還有提供 _gte _lte 的運算子(Operators),
所以當我們在瀏覽器這樣下 http://localhost:10000/api/v1/sales?count_gte=50
就可以取得 count 大於等於 50 的資料,
像這樣:
https://ithelp.ithome.com.tw/upload/images/20220917/20129873Zy0L3n0nq5.png

所以現在我們一樣來新增一個人氣料理的按鈕,
按下去執行 searchData,
裡面會 call axios.get url 我們就這樣寫:

function searchData(){
... (略)
axios.get(`${hostUrl}/api/v1/sales?count_gte=${hitCount}`)
  .then(function (response) {
	  setSales(response.data);
  })
  .catch(function (error) {
	  alert("抓取資料錯誤,請確認後再試");
	  console.log(error);
  })
}
... (略)
<Button m={2} onClick={searchData} colorScheme="teal">人氣料理</Button>

那我們一樣來看看執行結果:

今天介紹了 filter ?& 的寫法,
這也是前端 call API 時常用到的語法,
當然前端也可以自己在語法將 API 回傳回來的資料再進行過濾就好,
不過在資料量多的時候這樣對頁面的 loading 其實很大,
例如全部有10,000筆資料,
但你想要的其實只有其中的50筆,
這時候 API 只回傳 50 筆給前端是最好的,
不然拿到10,000筆甚至更多,
會產生不必要的 loading。

那我們一樣明天再見啦~

參考文章

Filter

後記

一邊趕鐵人賽文章遇到地震!
而且這次搖滿大的QQ
剛才好像又有第二次orz
希望大家平安無事QQ
https://ithelp.ithome.com.tw/upload/images/20220917/20129873tswF5DM0OO.png


上一篇
[Day15] 要怎麼知道要 call 的 API url 是?那你必須先知道 routes
下一篇
[Day17] call API 會用的參數系列~用 _limit 來做簡單分頁
系列文
SPYxFRONTEND ~ 懂一點後端真是讓人哇哭哇哭30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言