iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
Modern Web

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

Day 28 - React Redux Container 實際運用 (取得store與執行action)

  • 分享至 

  • xImage
  •  
tags: iThome 鐵人賽 30天

接續上一篇,我們已經把store整個套用在component內了,接下來就是看要如何把store內的state撈出來給component使用。

Container

簡單介紹container,就是能把store的reducer state與action給取出來轉變成props傳入至component中,讓這些參數與動作能在之中自由呼叫使用。

照慣例,都一樣以實際我們實作的專案影片標記系統來改、舉例,先來看看哪個component是需要傳入reducer與action的。

首先是首頁 (.\src\components\Main\HomePage.jsx) 的資料呈現與API抓取資料後設定,都需要透過reducer與action來進行,而container我也習慣把檔案集中在另一個containers資料夾內,讓component與container分開 (有時候可能會有只需要component不需要container撈資料的情況,就可以看情況引用不同檔案)。

在container內依照component存放相對位置去建立檔案.\src\containers\Main\HomePage.jsx

import { connect } from 'react-redux'
// 把component引入
import HomePage from '../../components/Main/HomePage'
// 把藥使用的action引入
import { setData } from '../../action'

const mapStateToProps = (state) => ({
  // 取出reducer內的state
  home: state.home
})

const mapDispatchToProps = {
  // 取出action
  setData,
}

// 整合reducer與action進入props
export default connect(mapStateToProps, mapDispatchToProps)(HomePage)

更改引用component入徑變成引用container

更改HomePage引入的位置 (改成container的位置):

import React from 'react'
import { Box } from '@mui/material'
import { Route, Routes, Navigate } from 'react-router-dom'
import HomePage from '../containers/Main/HomePage' // 更改成container所在地
import WatchPage from './Main/WatchPage'

export default function Main() {
  return (
    <Box sx={{ bgcolor: '#999', flex: "1 1 auto" }}>
      <Routes>
        <Route path="/watch" element={<WatchPage />} />
        <Route path="/" element={<HomePage />} />
        <Route path="*" element={<Navigate to="/" />} />
      </Routes>
    </Box>
  )
}

測試取出資料

我們將昨天設定的reducer home的預設資料取出來並console.log試試看,看資料是否有成功取得。

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

export default function HomePage(props) {
  const { home } = props // 取得reducer資料
  const [data, setData] = useState(null)

  console.log(home) // 查看是否成功

  useEffect(() => {
    getData()
  }, [])

  const getData = async () => {
    const data = await fetch('http://localhost:5000/api/Notes').then(res => res.json())
    setData(data)
  }

  return (
    <Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
      {!!data && data.map(d =>
        <VideoCard
          key={d.v}
          v={d.v}
          title={d.title}
        />
      )}
    </Box>
  )
}

console.log結果:

可以看到有成功取出資料了!

把資料來源變為從reducer的資料渲染

先新增action,讓資料可以從component設定至reducer。

.\src\action\home.js新增:

export const SET_DATA = "SET_DATA"
export const setData = (data) => action("SET_DATA", {data})

在reducer內建立相關應變措施改變initialState

.\src\reducer\home.js

// 把所有action引入
import * as action from '../action'

const initialState = {
  data: null
}

export default (state = initialState, { type, ...payload }) => {
  switch (type) {

    // 用辨別type來看要採取甚麼行動更改state
    case action.SET_DATA:
      return {
        ...state,
        data: payload.data,
      }

    default:
      return state
  }
}

將action從container中引入:

將component內的資料渲染與state變更狀態給替換掉,.\src\components\Main\HomePage.jsx

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

export default function HomePage(props) {
  const { home, setData } = props
  const { data } = home

  console.log(home)

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

  const getData = async () => {
    // fetch取得API的資料
    const data = await fetch('http://localhost:5000/api/Notes').then(res => res.json())
    setData(data)
  }

  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>
  )
}

可以看到更改後的畫面與資料依舊可以正常取得與呈現:

如法炮製修改MarkPage成React Redux的形狀

再來就是如法炮製,按照同樣的方法把MarkPage的標記也儲存在reducer之中,因為都是做一樣的事情,所以就不再列出來一一說明了,有興趣可以直接常看專案喔!


後記

剩下最後兩天,也差不多剩下最後兩個部分,把API接上並齊全功能,與剩下的Redux Saga,所以應該是可以如期完成吧~

附上專案:

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


上一篇
Day 27 - React Redux 基本介紹
下一篇
Day 29 - 完善功能與Saga介紹
系列文
新手進化日記,從React至Redux Saga30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言