【前言】
一樣先來回顧一下 Day2 Project 分析的使用者流程,今天來做第二步的**「驗證帳號讀取時的 Loading 特效」**。我發現寫 React 的心路歷程跟這個廣告很像,一下子在想為什麼沒感覺,一下子又在想為什麼你有感覺。很多東西到底怎麼出現的自己也不是很了解哈哈哈哈哈哈哈哈哈哈。
【(使用者看見的)前端與(後方運作的)後端】
【Loading Message】
利用到 Day 6 學到的 setIsPending()
來輸出 Loading Message。目前我的設想是:在使用者點下登入按鈕之後,跳出 MetaMask 的 API,到系統後端確認登入的這段時間,頁面都要呈現 Loading Message 或相關特效。
首先在 index.jsx
import useEffect()
及 useState()
。
import { useEffect, useState } from "react";
再來在 function return
之前加上 useState()
的敘述。
export function AccountBox(props) {
...
const [isPending, setIsPending] = useState(true);
...
return (
<AccountContext.Provider value={contextValue}>
...
</AccountContext.Provider>
);
}
在 useState()
的宣告以及return 之間加入 useEffect()
來隨時隨地偵測是否需要產出 Loading Message。附帶一提,這邊當然是為了讓 Loading 的效果出現才會特別用 setTimeout()
哈哈哈哈哈哈哈哈。因為我還沒有架設 json
的伺服器來供利用所以可以先忽略 fetch
的部分。
useEffect(() => {
setTimeout(() => {
fetch('...')
.then(res => {
return res.json();
})
.then(data => {
setIsPending(false);
})
}, 1000);
}, [])
目前的結果呈現是這樣,但跟我想像中的不一樣,應該要只出現 Loading Message,Loading 結束之後才出現登入介面才對! 後來才知道是我應該增加一個 bool
來選擇在 Loading 時先不要出現 <BoxContainer> ... </BoxContainer>
的資訊內容,等 Loading 結束後 isPending() == false
才會輸出登入介面。
export function AccountBox(props) {
...
const [isPending, setIsPending] = useState(true);
...
useEffect(() => {
setTimeout(() => {
setIsPending(false);
}, 1000);
}, [])
...
return (
<AccountContext.Provider value={contextValue}>
{ active === "signin" && (
<LoginWrapper>
{ isPending && <div>Loading...</div> }
<BoxContainer>
...
</BoxContainer>
</LoginWrapper>
)}
</AccountContext.Provider>
);
}
原本以為這個過程很簡單,沒想到在 useEffect()
上的 BUG 一堆,Loading Message 在 return
裡面的位置也需要思考一下。經過精簡再精簡的排除之後完整的程式碼大概長這樣!之後會把 json
的利用加回來,希望大家好好期待,這裡先著重在 Loading Message 的呈現。
export function AccountBox(props) {
...
const [isPending, setIsPending] = useState(true);
...
useEffect(() => {
setTimeout(() => {
setIsPending(false);
}, 1000);
}, [])
...
return (
<AccountContext.Provider value={contextValue}>
<LoginWrapper>
{ isPending && <div>Loading...</div> }
{ !isPending &&
<BoxContainer>
...
</BoxContainer>
}
</LoginWrapper>
</AccountContext.Provider>
);
}
【Loading Effect】
現在要開始對 Loading Message 加入特效,主要就是對 <div>Loading...</div>
這塊進行變化!如果只有使用 div
輸出文字的話是長這樣:(非常陽春)
經過在網路上多方尋找之後,我發現了一個非常棒的東西很符合需求,使用起來也沒有那麼複雜!首先來到以下這個網站找一個自己喜歡的 Loading 圖樣,然後調整自己喜歡的顏色、速度、尺寸。
然後在Command Line 執行以下程序:
npm install --save react-spinners
並且在 index.jsx
之中引入套件。其中 "~" 的部分為自己想要的 Loading 圖樣的名稱,我選擇的是 RingLoader,範例如下:
import ~ from "react-spinners/~";
e.g.
import RingLoader from "react-spinners/RingLoader";
這邊我使用的 Loading 特效及程式碼是這樣,因為發現可以覆寫 CSS 所以我對他做一點改變。
{ isPending &&
<RingLoader
size={170}
color={"#36D7B7"}
loading={isPending}
speedMultiplier={1.05}
css={override} />
}
記得在覆寫 CSS 之前要先 import emotion
。
import { css } from "@emotion/react";
const override = css`
display: block;
margin: 112% auto;
overflow:hidden;
`;
呈現的結果非常不錯!
原本我直接把程式碼丟進去 return 的時候想說今天的內容也未免太簡單了,結果 compiler error 了好久,他一直告訴我 "loading" 沒有宣告過,後來才發現原來我是使用 isPending 來當作是否在 Loading 的 bool。
【小結】
React 讓我有一種又驚又喜又怕,既期待又怕受傷害的感覺,每次看到很棒的特效或者前端的時候都會想實作看看,但每次元件的複雜程度還有未知的 BUG 都會一次次的打擊信心。不過我會繼續加油的,畢竟跟一開始完全對前端毫無涉獵的我相比,現在已經進步很多了吧!
【參考資料】
react-spinners
CSS overflow 屬性用法