iT邦幫忙

2021 iThome 鐵人賽

DAY 25
1
自我挑戰組

Re: 從 Next.js 開始的 React 生活系列 第 25

[Day25] 在 Codecademy 學 React ~ 終於來到 Hook 的世界 ‧ useState 篇 (2)

  • 分享至 

  • xImage
  •  

前言

快開天窗了先把目前進度 po 出來再說orz
今天文章重點在 setState 搭配 ...prev 的運用~

本日正文

當我今天想要做一個偶像挑選器(?),
要怎麼做?

首先我先新增一個檔案 idolItems.js
裡面放上各個偶像的名字跟圖片網址,
像這樣:

export const idolList = [
  {
    playerName: "戴資穎",
    picture:
      "https://im.marieclaire.com.tw/m800c533h100b0/assets/mc/202108/6106B3F21135F1627829234.jpeg"
  },
... (略)

然後我再新增一個 Game.js
裡面要 import idolItems.js 的 idolList component,
並利用 <ul> <li> 搭配 .map 把 idolList 陣列裡面一個一個元素各別把名字跟圖片顯示出來,
重點是要在 <li> 綁上 value={index} 的屬性,
這樣之後才能拿來點擊後判斷用,
像這樣:

import React, { useState } from "react";
import { idolList } from "./idolItems.js";

export const Game = () => {
  };
  return (
    <>
      <h2>你的偶像是:</h2>
      {answerList.map((answer) => (
        <>
          <div>{idolList[answer].playerName}</div>
          <img
            width="100px"
            src={idolList[answer].picture}
            alt={idolList[answer].name}
          />
        </>
      ))}
      <h2>請點選你喜歡的偶像(名字):</h2>
      <ul>
        {idolList.map((idol, index) => (
          <>
            <li value={index} onClick={handleChange}>
              {idol.playerName}
            </li>
            <img width="100px" src={idol.picture} alt={idol.name} />
          </>
        ))}
      </ul>
    </>
  );
};

https://ithelp.ithome.com.tw/upload/images/20210927/20129873RxKjQkTksb.png

再來重頭戲來了,
我想要點選名字上面就出現我的點選結果要怎麼做?
首先我先宣告 answerList,以及相對應設值的 setAnswer,
並將初始值設為空陣列,
像這樣:

const [answerList, setAnswer] = useState([]);

再來要宣告一個 handleChange 的 function,
在點擊 <LI> 要執行,
這邊先貼程式:

const handleChange = (event) => {
    if (event.target.nodeName === "LI") {
      setAnswer((prev) => {
        return [event.target.value, ...prev];
      });
    }
  };

這邊的重點有兩個,

  1. 第一個是 ...prev
 setAnswer((prev) => {
    return [event.target.value, ...prev];
  });

這邊的意思是將 setAnswer 所對應到的 state answerList 陣列裡面的內容存為 ...prev
再來我要 append 一個新元素到 answerList 陣列只需要這樣寫 新的值,...prev 即可,
如果沒有寫 ...prev 的話則每次只要你一點擊就會把 answerList 重新蓋掉。

其實 ...prev 應該是 JavaScript 的語法,
只是我到現在才知道怎麼用orz XD
Spread syntax (...)

  1. 第二個重點是 event.target.nodeName
if (event.target.nodeName === "LI")
}

為什麼要加這個,因為我剛剛在 <li> 裡面放了圖片的元件,
然後只要點擊到圖片,
就會出現 error,
這個原因是因為只有 <li>value={index}
當你點擊到 <img> 因為 event.target.value 為空,

(prev) => {
    return [event.target.value, ...prev];
  })

所以在處理這句會發生錯誤哦!
這邊為大家示範一下沒加出現的錯誤訊息:
https://ithelp.ithome.com.tw/upload/images/20210927/201298735EU2BJRDCN.png

也因此只有點到 <li> 上的文字才會處理哦!
這應該也算是 exception handling (例外處理) 的一種,
這很重要哦!

哦對,然後當然要記得在 App.js 加入 <Game /> 的 component 哦,
像這樣:
[App.js]

<div className="App">
  <Game />
</div>

那我們來看看成果:

附上本日程式:Day25 - useState (Codecademy)

後記

差點趕不上又遇到 bug orz
超驚險QQ
發文前在寫前端又參考了我前幾天發的文章XD
覺得勵志XD


上一篇
[Day24] 在 Codecademy 學 React ~ 終於來到 Hook 的世界 ‧ useState 篇 (1)
下一篇
[Day26] 在 Codecademy 學 React ~ 你知道用 useState 就能完成簡單小遊戲嗎?大家一起來玩終極密碼吧!
系列文
Re: 從 Next.js 開始的 React 生活31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言