React Native、redux、redux-saga发起请求全过程简单解说

以下代码来源于我的项目NovelAPP:https://github.com/SemperChen/NovelAPP

 

首先是从this.props.dispatch发起网络请求,如MainDetail(BookDetailPage的子组件)

js/commons/MainDetail.js

下面是请求书籍详情, bookDetailUrl是请求书籍详情网址

 componentDidMount() {
    ...
    this.props.dispatch(requestDetail(this.bookDetailUrl))
    ...
 }

js/actions/detail.js

...
export function requestDetail(bookDetailUrl) {
    return {
        type: REQUEST_DETAIL,
        bookDetailUrl
    };
}
...

我们从上面代码可以看出,其实

requestDetail(this.bookDetailUrl)

这个方法返回的就是以下这个action对象

{
        type: REQUEST_DETAIL,
        bookDetailUrl
}

即代码

this.props.dispatch(requestDetail(this.bookDetailUrl))

可以看成

    this.props.dispatch({
        type: REQUEST_DETAIL,
        bookDetailUrl
    })

当dispatch把action即{ type: REQUEST_DETAIL, bookDetailUrl } 发出去之后,redux收到这个action请求,会执行以下代码中的detail(state=initalState, action)方法

js/reducers/detail.js

export default function detail(state = initialState, action) {
    switch (action.type) {
        case REQUEST_DETAIL:
        return {
            ...state,
            isFetchingDetail:true
        };
        ...
    }
}

并返回以下对象

{
    ...state,
    isFetchingDetail:true
};

然后会执行以下代码中mapStateToProps这个方法 ,将isFetchingDetail=true传进来

js/commons/MainDetail.js

function mapStateToProps(state) {
    const {bookDetail, isFetchingDetail} = state.detail;
    const {items: bookmarks} = state.bookmarks;
    return {bookDetail, bookmarks, isFetchingDetail}
}

上面mapStateToProps方法执行后,会重新渲染render等方法

 render() {
        ...
        return (
            <View>
                        
            {this.props.isFetchingDetail
                 ?
                 <View style={{marginTop: 10, justifyContent: 'center',         
                 alignItems: 'center'}}>
                    <ActivityIndicator
                        animating={true}
                        color={appTheme.primaryColor}
                        size="small"
                        />
                           <Text style={{color: appTheme.primaryColor}}>加载中,        
                           请稍等</Text>
                 </View>

                 : null
             }
            ...
            </View>
        )
    }

这时,因为上面代码中this.props.isFetchingDetail=true,加载中,请稍等 这几个字便出现,如图

与此同时saga也收到REQUEST_DETAIL请求

js/sagas/index.js

const rootSaga = function* root() {
    yield all([
        ...
        takeLatestFetch(REQUEST_DETAIL,fetchBookDetail),
        ...
    ])
};
export default rootSaga;

以上takeLatestFetch(REQUEST_DETAIL, fetchBookDetail),这个方法监听到REQUEST_DETAIL请求后,就会执行fetchBookDetail 这个方法,并将action{ type:  REQUEST_DETAIL, bookDetailUrl }bookDetailUrl作为参数

js/sagas/detail.js

export function* fetchBookDetail(params) {
    try {
        const {bookDetailUrl} = params;
        const bookDetail = yield call(fetchJSON, bookDetailUrl);
        yield put(receiveDetail(bookDetail))
    } catch (e) {
        console.log('detail fetchBookDetail:', e.message);

    }

};

 

const bookDetail = yield call(fetchJSON, bookDetailUrl);

 执行到上面这一步的时候,会把bookDetailUrl网址作为fetchJSON方法的参数,发起网络请求,并将请求结果返回,即bookDetail

js/utils/HttpUtil

export function fetchJSON(url) {
    return new Promise((resolve, reject) => {
        fetch(url, {
            headers: {
                'Content-Type': 'application/json',
                'Accept-Charset': 'utf-8',
                'User-Agent': 'Mozilla/5.0 (Linux; X11)',
            }
        })
            .then((response) => {
                return response.json()
            })
            .catch((error) => {
                reject(error);
            }).then((responseData) => {
            if (!responseData) {
                reject(new Error('fetchJSON:responseData is null'));
                return;
            }
            resolve(responseData);
        }).done();
    })
}

 

yield put(receiveDetail(bookDetail))

执行到这一步时候,saga会将网络请求返回的结果bookDetail发出去,类似于刚开始介绍的this.props.dispatch

 

js/actions/receiveDetail.js

export function receiveDetail(bookDetail) {
    return {
        type: RECEIVE_DETAIL,
        bookDetail
    };
}

因为receiveDetail(bookDetail) 返回的值是{ type:  RECEIVE_DETAIL, bookDetail } ,所以yield put(receiveDetail(bookDetail))相当于

yield put({
        type: RECEIVE_DETAIL,
        bookDetail
    })

或相当于

this.props.dispatch({
        type: RECEIVE_DETAIL,
        bookDetail
    })

然后redux收到RECEIVE_DETAIL请求后,会执行以下方法,并将action:{type:  RECEIVE_DETAIL, bookDetail}传到下面代码里,然后action.type跟case RECEIVE_DETAIL匹配,返回{ ...state, bookDetail:  action.bookDetail, isFetchingDetail: false }

js/reducers/detail.js

export default function detail(state = initialState, action) {
    switch (action.type) {
       ...
        case RECEIVE_DETAIL:
            return {
                ...state,
                bookDetail: action.bookDetail,
                isFetchingDetail:false
            };
        ...
    }
}

然后会将上面bookDetail和isFetchingDetail传到mapStateToProps

js/commons/MainDetail.js

function mapStateToProps(state) {
    const {bookDetail, isFetchingDetail} = state.detail;
    const {items: bookmarks} = state.bookmarks;
    return {bookDetail, bookmarks, isFetchingDetail}
}

render将重新渲染,返回的bookDetail书籍详情将会显示

render(){
   ...
   this.bookDetail = this.props.bookDetail;
   return(
    <View>
      ...
      <Text>{this.bookDetail.bookName}</Text>
      ...
    </View>
   )
   ...

}

因为返回的 isFetchingDetail=false,下图中的加载中,请稍等将消失

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值