iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
自我挑戰組

React 30 天學習歷程系列 第 21

【Day 21】React 中請求遠端資料

  • 分享至 

  • xImage
  •  

元件內請求資料

通常只有在產品功能比較簡單的情況下才會在元件內進行遠端資料的請求,因為功能複雜的產品,往往請求的 API 也比較多且複雜,若在元件內處理,會讓元件顯得很混亂,難以維護,但這邊我們還是簡單示範一下元件內請求資料的方式。

class component 請求資料

在 class component 請求資料,通常是在 componentDidMount 中執行,如下面的範例

class UserProfile extends React.Component {
    state = {
        data: []
    }

    componentDidMount () {
        // ajax、fetch、axios 請求遠端資料
        if (data) {
            this.setState({data: data})
        }
    }

    render() {
        const { data } = this.state
        return (
            <div>
                { data }
            </div>
        );
    }
}

function component 請求資料

前面的文章有提過,function component 是沒有生命週期的,但是它可以借助 react hook 中的 useEffect 函式來處理資料請求,有關 react hook 詳細的部分,會在後面的文章在做整理。useEffect 相當於 class component 中的 componentDidMount,他接受兩個參數,第一個參數是函式,可以在裡面做非同步行為,像是資料請求,然後再更新資料。下面的範例中我們還有使用到 useState 這個方法,也是 react hook 的一個函式,基本上是調用這個函式來做資料管理,這部分會在後面的文章中再做詳細整理,這邊只是一個簡易範例。

import React, { useEffect, useState } from 'react';

const UserProfile = () => {
    const [data, setData] = useState(null)

    useEffect(async () => {
        // ajax、fetch、axios 請求遠端資料
        if (result) {
            setData(result.data)
        }
    })

    return <div>
        { data }
    </div>
}

在元件外部處理資料

元件外部的資料請求,指的通常是在元件外部請求資料後,由第三方套件做資料管理。通常產品開發上資料很複雜時,都會使用第三方套件來做資料管理,比方說 redux、mobx、dva,它們都有很好的資料管理功能。課程中是以 dva 為例,dva 提供了一個 model 模組做資料管理,下面是一個簡單的範例,大概呈現 dva 是如何管理資料。

  1. 首先我們先透過一個函式去向遠端請求資料
const fetchUserData = () => {
    return fetch('/api/userData').then(res => res.json())
}
  1. 接著我們透過 dva 的 model 層處理和更新資料。
  • namespace 是 model 的名字,model 內也有 state 屬性,但是這是 dva 本身的 state(元件外部的 state),和 React 元件中的 state 不是同一個。
  • effects 是處理副作用的,遠端資料請求就是在這邊處理,會叫副作用是因為這讓我們的函式變得比較不純。另外,需要注意在 effects 中是使用 generator 來處理同步和非同步,async await 是不能用的。我們利用 call 去調用前面的 fetchUserData 來取得遠端資料,在用 put 去更新,put 中的參數,type 是去指定使用的函式,在這邊是使用 reducers 裡面的 updateUserDatapayload 是傳送到函式的參數。
  • reducers 中會得到舊的資料狀態(state)和更新的資料狀態(action.payload),整合後返回一個新的 state
app.model({
    namespace: 'userData',
    state: {
        userData: []
    },
    effects: {
        //generator 處理非同步
        *getUserData(action, {call, put}) {
            const user = yield call(fetchUserData, 1000)
            yield put({type: 'updateUserData', payload: { user }})
        }
    },
    reducers: {
        updateUserData( state, action) {
            return {...state, ...action.payload}
        }
    },
    subscriptions: {
        //訂閱
    }
})
  1. 將 dva 的 state 同步更新到 React 元件中,要使用 dva 提供的一個函式 connect,這個函式可以將 dva 中的資料和元件連結。如下面的程式碼,UserProfile 是我們在 React 中自訂的元件,透過 connect 去取得資料,並返回一個全新的元件。
import { connect } from 'dva'

connect((state) => {
    return { user: state.user }
})(UserProfile)
  1. 最後我們可以在 React 元件中去取得資料,我們在 componentDidMount 裡面利用 dispatch 去調用 dva modeleffects 中的函式,這樣就會取得資料並更新資料,並完成元件的更新。
class UserProfile extends React.Component {

    componentDidMount () {
        this.props.dispatch({ type: getUserData})
    }

    render() {
        const { userData } = this.props
        return (
            <div>
                { userData }
            </div>
        );
    }
}

小結

基本上只要專案有一定規模,通常還是會採用第三方套件去管理遠端請求回來的資料,不只是開發上比較方便,維護性也比較高。另外,通常 API 複雜的產品,其實也會統一 API 的管理,這部份我們會在下一篇提到。


上一篇
【Day 20】React Portals 和 PropTypes 檢查
下一篇
【Day 22】遠端資料請求方式以及 API 統一管理
系列文
React 30 天學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言