React Hooks完成异步要求实例—useReducer、useContext和useEffect替代Redux计划

本文是进修了2018年新鲜出炉的React Hooks提案以后,针对
异步要求数据写的一个案例。注重,本文假设了:

1.你已开端相识
hooks的寄义了,假如不相识还请移步
官方文档。(实在有过翻译的主意,不过印记中文一直在翻译,就是比较慢啦)

2.你运用
Redux完成过异步
Action(非必须,只是本文不触及该部份学问而直接运用)

3.你听说过
axios或许
fetch(假如没有,那末设想一下原生js的
promise完成异步要求,或许去进修下这俩库)

悉数代码拜见堆栈:
github | Marckon挑选
hooks-onlineShop分支以及
master分支检察

本文并不是最好实践,若有更好的要领或发明文中马虎,迎接斧正!

前序计划(不想看可以直接跳过)

  • 不斟酌引入Redux

经由过程进修React生命周期,我们晓得合适举行异步要求的处所是componentDidMount钩子函数内。因而,当你不须要斟酌状况治理时,以往的要领很简单:

class App extends React.Component{
    componentDidMount(){
        axios.get('/your/api')
            .then(res=>/*...*/)
    }
}
  • 引入Redux举行状况治理

当你决议运用Redux举行状况治理时,比方将异步猎取到的数据储存在store中,事变就最先庞杂起来了。依据Redux的官方文档案例来看,为了完成异步action,你还得须要一个类似于redux-thunk的第三方库来剖析你的异步action

requestAction.js: 定义异步要求action的处所

//这是一个异步action,分发了两个同步action,redux-thunk可以明白它
const fetchGoodsList = url => dispatch => {
    dispatch(requestGoodsList());
    axios.get(url)
        .then(res=>{
            dispatch(receiveGoodsList(res.data))
        })
};

requestReducer.js: 处置惩罚同步action

const requestReducer=(state=initialState,action)=>{
    switch (action.type) {
        case REQUEST_GOODSLIST:
            return Object.assign({},state,{
                isFetching: true
            });
        case RECEIVE_GOODSLIST:
            return Object.assign({},state,{
                isFetching:false,
                goodsList:action.goodsList
            });
        default:
            return state;
    }
};

App Component :你引入redux store和redux-thunk中间件的处所

import {Provider} from 'react-redux';
import thunkMiddleWare from 'redux-thunk';
import {createStore,applyMiddleware} from 'redux';
//other imports

let store=createStore(
    rootReducer,
    //这里要运用中间件,才可以完成异步要求
    applyMiddleware(
        thunkMiddleWare,
        myMiddleWare,

    )
);
class App extends React.Component{
    render(){
        return (
            <Provider store={store}>
                <RootComponent/>
            </Provider>
        )
    }
}

GoodsList Component :须要举行异步要求的组件

class GoodsList extends React.Component{
    //...
    componentDidMount(){
        this.props.fetchGoodsList('your/url');
    }
    //...
}
const mapDispatchToProps={
    fetchGoodsList
}
export default connect(
    mapStateToProps,
    mapDispatchToProps
)(GoodsList);

完全代码:branch:master-onlineShop

运用HooksuseReducer()useContext()

总之运用Redux很累,固然,你可以不运用Redux,直接经由过程props层层通报,或许运用context都可以。只不过本文我们学过了useReducer,运用到了Redux的头脑,总要试着用一下。

这里你不须要引入别的任何第三方库了,简简单单地运用React@16.7.0-alpha.2版本就好啦

很主要的一点就是——函数式组件,如今React引荐我们这么做,可以基本上替代class写法。

函数署名

  1. useReducer(reducer,initialState)
  2. useContext(ctxObj)
  3. useEffect(effectFunction,[dependencyValues])

概览-你须要编写什么

  1. action.js:

    • 我们还运用redux的头脑,编写action
  2. reducer.js:

    • 处置惩罚action,不同于reduxreducer,这里我们可以不必供应初始状况
  3. 根组件:

    • Provider供应给子组件context
    • useReducer定义的位置,引入一个reducer而且供应初始状况initialState
  4. 子组件:

    • useContext定义的位置,猎取先人组件供应的context
    • useEffect用于举行异步要求

完成

1.action.js:我们运用action建立函数

const REQUEST_GOODSLIST = "REQUEST_GOODSLIST";
const RECEIVE_GOODSLIST = "RECEIVE_GOODSLIST";

//最先要求
const requestGoodsList = () => ({
    type: REQUEST_GOODSLIST
});

//接收到数据
const receiveGoodsList = json => ({
    type: RECEIVE_GOODSLIST,
    goodsList: json.goodsList,
    receivedAt: Date.now()
});

export {
    RECEIVE_GOODSLIST,
    REQUEST_GOODSLIST,
    receiveGoodsList,
    requestGoodsList,
}

2.reducer.js:推断action的范例并举行响应处置惩罚,更新state

import {
    RECEIVE_GOODSLIST,
    REQUEST_GOODSLIST,
} from "../..";


export const fetchReducer=(state,action)=>{
    switch (action.type) {
        case REQUEST_GOODSLIST:
            return Object.assign({},state,{
                isFetching: true
            });
        case RECEIVE_GOODSLIST:
            return Object.assign({},state,{
                isFetching:false,
                goodsList:state.goodsList.concat(action.goodsList)
            });
        default:
            return state;
    }
};

3.根组件:引入reducer.js

import React,{useReducer} from 'react';
import {fetchReducer} from '..';

//建立并export上下文
export const FetchesContext = React.createContext(null);

function RootComponent() {
    //第二个参数为state的初始状况
    const [fetchesState, fetchDispatch] = useReducer(fetchReducer, {
            isFetching: false,
            goodsList: []
        });
    return (
        //将dispatch要领和状况都作为context通报给子组件
         <FetchesContext.Provider value={{fetchesState,dispatch:fetchDispatch}}>
             //...
             //用到context的一个子组件
             <ComponentToUseContext/>
         </FetchesContext.Provider>
    )
}

4.子组件:引入FetchesContext

import {FetchesContext} from "../RootComponent";
import React, {useContext, useEffect,useState} from 'react';
import axios from 'axios';

function GoodsList() {

    //猎取上下文
    const ctx = useContext(FetchesContext);
    
    //一个推断是不是从新猎取的state变量
    const [reFetch,setReFetch]=useState(false);

    //具有异步挪用副作用的useEffect
    useEffect(() => {
        //起首分发一个最先异步猎取数据的action
        ctx.dispatch(requestGoodsList());
            axios.get(proxyGoodsListAPI())
                .then(res=>{
                    //猎取到数据后分发一个action,关照reducer更新状况
                    ctx.dispatch(receiveGoodsList(res.data))
                })
      //第二个参数reFetch指的是只有当reFetch变量值转变才从新衬着
    },[reFetch]);

    return (
        <div onScroll={handleScroll}>
            {
                //children
            }
        </div>
    )
}

完全代码拜见:branch:hooks-onlineShop

目次构造

我的目次构造也许如许:

src
  |- actions
     |- fetchAction.js
  |- components
     |-...
  |- reducers
     |- fetchReducer.js
  |- index.js

注重点

  1. 运用useContext()时刻我们不须要运用Consumer了。但不要遗忘exportimport上下文对象
  2. useEffect()可以看作是class写法的componentDidMountcomponentDidUpdate以及componentWillUnMount三个钩子函数的组合。

    • 当返回了一个函数的时刻,这个函数就在compnentWillUnMount生命周期挪用
    • 默许地,传给useEffect的第一个参数会在每次(包括第一次)数据更新时从新挪用
    • 当给useEffect()传入了第二个参数(数组范例)的时刻,effect函数会在第一次衬着时挪用,其他仅当数组中的任一元素发作转变时才会挪用。这相当于我们掌握了组件的update生命周期
    • useEffect()第二个数组为空则意味着仅在componentDidMount周期实行一次
  3. 代码堆栈里运用了Mock.js阻拦api要求以及ant-design第三UI方库。现在代码比较大略。
    原文作者:Marckon
    原文地址: https://segmentfault.com/a/1190000017209855
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞