iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

新手進化日記,從React至Redux Saga系列 第 20

Day 20 - Container Wrapper包裝影片卡片 / Array Mapping

  • 分享至 

  • xImage
  •  
tags: iThome 鐵人賽 30天

今天要處理的是讓每個頁面都有自己的Container來包裝排版,畢竟每個頁面的排版不一定都相同,這個專案主要就兩個頁面,首頁及標記編輯頁面,兩個預想的排版差異滿大的,所以就選擇分開裝囉!

HomePage Wrapper

那就先來做首頁的Container吧!

先在/src/components裡新增main資料夾,這個資料夾我打算把主要畫面呈現的component集中放置在內。再來在main內新增HomePage.jsx

之後就是開始調版面時間啦,就大概調到自己覺得看得下去的地步,當然對自己有美觀的要求就加油吧,我先放棄XD,大概調個間距就好~

這是我最終調整完的版本:
HomePage.jsx:

import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import VideoCard from '../VideoCard'

export default function HomePage() {
    return (
        <Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
             <VideoCard
                v={"Ga22mpTDS6A"}
                title={"東京版《Joe是要對決》日幣30000元的奢華壽喜燒對決日幣600元的平價壽喜燒!Ep127@徐海莉 Hailey@流川莉蘿 Rilo ch."}
            />
            <VideoCard
                v={"SxQgIJ3rQ3c"}
                title={"NEAL對決秋天的王者李宰赫!Royal Roader再度誕生!個人賽決賽SET 2《2022 跑跑卡丁車聯賽 S2》"}
            />
        </Box>
    )
}

VideoCard.jsx:

import React from 'react'
import { Card, CardMedia, CardContent, Typography } from '@mui/material'
import { Link } from 'react-router-dom' // 導入Link

export default function VideoCard(props) {
  const { v, title } = props

  return (
    <Card sx={{ maxWidth: 480, m: 1 }}>
      <Link className='reset' to={`/watch?v=${v}`}>
        <CardMedia
          component="img"
          // height="360"
          image={`https://img.youtube.com/vi/${v}/hqdefault.jpg`}
          alt="green iguana"
        />
        <CardContent>
          <Typography gutterBottom variant="h5" component="div" className='twoline'>
            {title}
          </Typography>
        </CardContent>
      </Link>
    </Card>

  )
}

新增的CSS (為了把Link產生的超連結變色和hover拿掉):

.reset{
  text-decoration: none;
  color: #000;
  outline: none;
}

Array Mapping

先看看上面的HomePage.jsx,可以發現目前卡片還都是寫死的情況,接下來會模擬API已經取得資料後,當作參數傳進去的方式去用mapping讓卡片渲染出來。

因為要取得資料的時間點會是在訪問HomePage的時候,所以把模擬的data放在HomePage中:

import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import VideoCard from '../VideoCard'

export default function HomePage() {
    const [data, setData] = useState(null)

    useEffect(() => {
        // 第一次進入HomePage.jsx時去取得資料
        getData()
    }, [])

    const getData = () => {
        // 模擬API取得資料
        setData(
            [
                { v: "Ga22mpTDS6A", title: "東京版《Joe是要對決》日幣30000元的奢華壽喜燒對決日幣600元的平價壽喜燒!Ep127@徐海莉 Hailey@流川莉蘿 Rilo ch." },
                { v: "SxQgIJ3rQ3c", title: "NEAL對決秋天的王者李宰赫!Royal Roader再度誕生!個人賽決賽SET 2《2022 跑跑卡丁車聯賽 S2》" }
            ]
        )
    }

    return (
        <Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
            {/** 用.map的方式把array的資料一個一個渲染出來 */}
            {!!data && data.map(d =>
                <VideoCard
                    // key用來幫助React分辨哪些項目被改變、增加或刪除
                    key={d.v}
                    v={d.v}
                    title={d.title}
                />
            )}
        </Box>
    )
}

Key

在mapping中有個重點,就是如果是mapping component的話要記得在component裡加入key參數,並給予一個在這個陣列裡不會重複出現的值。

當然如果裡面的元素不會變動的話有個偷懶的方法,但是不建議使用:

{!!data && data.map((d, index) =>
    <VideoCard
        key={index}
        v={d.v}
        title={d.title}
    />
)}

偷懶的方法藏在map的第二個參數裡,index代表是array的第幾個值 (從0開始),所以一定是唯一的,但並不推薦使用在會改變順序的情況,可能會發生意想不到的錯誤。

成果


可以發現array的資料成功變出來了。

當然我們也可以模擬資料很多的情況,看看會變甚麼樣子吧!

後記

整理完後版面是不是看起來清爽很多了呢?再來就是處理編輯頁面啦~不過居然剩下10天了,時間過得好快,開始擔心結束的時候還沒講完了...?

附上專案:2022-iThomeIronman

對資安或Mapbox有興趣的話也可以觀看我們團隊的鐵人發文喔~


上一篇
Day 19 - Switch\Redirect選擇你的網頁人生路徑
下一篇
Day 21 - YouTube Iframe API: 打造全面的YT控制器component
系列文
新手進化日記,從React至Redux Saga30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言