通常只有在產品功能比較簡單的情況下才會在元件內進行遠端資料的請求,因為功能複雜的產品,往往請求的 API 也比較多且複雜,若在元件內處理,會讓元件顯得很混亂,難以維護,但這邊我們還是簡單示範一下元件內請求資料的方式。
在 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 是沒有生命週期的,但是它可以借助 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 是如何管理資料。
const fetchUserData = () => {
return fetch('/api/userData').then(res => res.json())
}
model
層處理和更新資料。namespace
是 model 的名字,model 內也有 state
屬性,但是這是 dva 本身的 state
(元件外部的 state
),和 React 元件中的 state
不是同一個。effects
是處理副作用的,遠端資料請求就是在這邊處理,會叫副作用是因為這讓我們的函式變得比較不純。另外,需要注意在 effects
中是使用 generator
來處理同步和非同步,async await
是不能用的。我們利用 call
去調用前面的 fetchUserData
來取得遠端資料,在用 put
去更新,put
中的參數,type
是去指定使用的函式,在這邊是使用 reducers
裡面的 updateUserData
,payload
是傳送到函式的參數。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: {
//訂閱
}
})
state
同步更新到 React 元件中,要使用 dva 提供的一個函式 connect
,這個函式可以將 dva 中的資料和元件連結。如下面的程式碼,UserProfile
是我們在 React 中自訂的元件,透過 connect
去取得資料,並返回一個全新的元件。import { connect } from 'dva'
connect((state) => {
return { user: state.user }
})(UserProfile)
componentDidMount
裡面利用 dispatch
去調用 dva model
的 effects
中的函式,這樣就會取得資料並更新資料,並完成元件的更新。class UserProfile extends React.Component {
componentDidMount () {
this.props.dispatch({ type: getUserData})
}
render() {
const { userData } = this.props
return (
<div>
{ userData }
</div>
);
}
}
基本上只要專案有一定規模,通常還是會採用第三方套件去管理遠端請求回來的資料,不只是開發上比較方便,維護性也比較高。另外,通常 API 複雜的產品,其實也會統一 API 的管理,這部份我們會在下一篇提到。