跳至主要内容

[react] React常用的JavaScript語法 - 可選鏈

JavaScript

要是我們並不清楚取得的資料是否為物件,又使用物件取值的方式去呼叫,且沒有做任何的判斷,程式就會報出錯誤:

index.js
let food = null;console.log(food.name); // error : Cannot read properties of null (reading 'name')

所以判斷一個物件裡面有沒有我們要取得的 key,可以使用以下方法來確認:

index.js
let food = { name: "apple" };if (food != null) {  console.log(food.name); // output : apple}// orif (food) {  console.log(food.name); // output : apple}

或是使用可選鏈(optional chaining),來檢查該物件內是否有我們要取得的 key:

index.js
let food = { name: "apple" };if (food?.name) {  console.log(food.name); // output : apple}//不會進到這個if 因為food物件內並沒有名為color的keyif (food?.color) {  console.log(food.color);}
備註

可選鏈的使用方式為在物件名稱的後面加上 ?.

而 food?.name 為檢查 food 物件內有沒有名為 name 的 key。

假釋今天物件內有其他 function,可以使用可選鏈先確認 function 是否存在,存在的話再執行它:

index.js
let food = {  name: "apple",  color: "red",  getFoodData: () => {    console.log("getFoodData..."); // output : getFoodData...  },};food?.getFoodData?.();

React

現在使用 fetch API 來取得 jsonplaceholder 的提供的 posts 資料,並把 limit 設置為 5,這樣我們每次 fetch 只會取得 5 筆 post 的資料。

App.js
function App() {  const [posts, setPosts] = useState(null);  useEffect(() => {    const getPostData = async () => {      const response = await fetch(        "https://jsonplaceholder.typicode.com/posts?_limit=5"      );      const data = await response.json();      setPosts(data);    };    getPostData();  }, []);  console.log(posts); // output : (5) [{…}, {…}, {…}, {…}, {…}]  return (    <div className="App">      {posts.map((post) => (        <p>{post.title}</p>      ))}    </div>  );}

但使用上面的寫法只要重新整理網頁後,程式就會報出錯誤,這是因為 posts 這個 state 在初始化時為 null,而 null 這個型態並沒有支援 map function,所以才會出現錯誤訊息。

Image

而我們可以在程式中加上判斷,判斷 posts 是否為 null,如果是的話就回傳 Loading 文字。

App.js
function App() {  const [posts, setPosts] = useState(null);  useEffect(() => {    const getPostData = async () => {      const response = await fetch(        "https://jsonplaceholder.typicode.com/posts?_limit=5"      );      const data = await response.json();      setPosts(data);    };    getPostData();  }, []);  console.log(posts);  if (posts == null) {    return <h1>Loading...</h1>;  }  return (    <div className="App">      {posts.map((post) => (        <p>{post.title}</p>      ))}    </div>  );}

Image

或是直接在 posts 後面加上可選鏈,這樣就不用撰寫多餘的判斷程式碼:

App.js
function App() {  const [posts, setPosts] = useState(null);  useEffect(() => {    const getPostData = async () => {      const response = await fetch(        "https://jsonplaceholder.typicode.com/posts?_limit=5"      );      const data = await response.json();      setPosts(data);    };    getPostData();  }, []);  console.log(posts); // output : (5) [{…}, {…}, {…}, {…}, {…}]  return (    <div className="App">      {posts?.map((post) => (        <p>{post.title}</p>      ))}    </div>  );}