- 通常asynchronous request有三個stage
- Request開始
- Request成功
- Request失敗
const initialState = {
data: [],
isFetching: false,
error: ''
}
- 這個Reducer長的如下,我們處理了上面提到的三個stage
function reducer (state = initialState, action) {
switch (action.type) {
case 'FETCHING_DATA' :
return Object.assign({}, state, {
isFetching: true
})
case 'FETCHING_DATA_ERROR' :
return Object.assign({}, state, {
isFetching: false,
error: action.error,
})
case 'FETCHING_DATA_SUCCESS' :
return Object.assign({}, state, {
isFetching: false,
error: '',
data: action.data
})
}
}
function fetchingData () {
return {
type: 'FETCHING_DATA'
}
}
function fetchingDataError (error) {
return {
type: 'FETCHING_DATA_ERROR',
error: error.msg
}
}
function fetchingDataSuccess (data) {
return {
type: 'FETCHING_DATA_SUCCESS',
data,
}
}
- 接下來考慮一個常見的情況,我們可能在Component要mount的時候去發出asynchronous request,假設getData( )是一個asynchronous function會回傳一個Promise,他會以如下的方式跟Action Creator整合
componentDidMount () {
fetchingData()
getData()
.then((data) => fetchingDataSuccess(data))
.catch((error) => fetchingDataError(error))
}
- 上面那樣看起來不錯,只是要把那些Action Creator都import到我們的Component有點麻煩,而且還得用bindActionCreators把他們跟dispatch bind起來,以及做PropTypes的檢查等。是不是把這些邏輯封裝到另一個Action Creator會更好呢?假設有一個Action Creator叫做fetchAndHandleData可以做到這些,那麼componentDidMount只要像這樣就好:
componentDidMount () {
fetchAndHandleData()
}
- 只是要做到這樣的話,就必須讓那個Action Creator得以存取dispatch,這就是redux-thunk出現的原因,他的想法是Action Creator不是回傳一個物件,而是回傳一個傳入dispatch的function,以上面的fetchAndHandleData為例大概會長的像這樣:
function fetchAndHandleData () {
return function (dispatch) {
dispatch(fetchingData())
getData()
.then((data) => dispatch(fetchingDataSuccess(data)))
.catch((error) => dispatch(fetchingDataError(error)))
}
}
- 最後是實作的時候要import的東西,以及在createStore( )時多帶入一個參數
...
import thunk from 'redux-thunk'
import { createStore, applyMiddleware } from 'redux'
...
const store = createStore(users, applyMiddleware(thunk))
...
沒有留言:
張貼留言