摘要:本文是學(xué)習(xí)了年新鮮出爐的提案之后,針對異步請求數(shù)據(jù)寫的一個案例。注意,本文假設(shè)了你已經(jīng)初步了解的含義了,如果不了解還請移步官方文檔。但不要忘記和上下文對象可以看做是寫法的以及三個鉤子函數(shù)的組合。
本文是學(xué)習(xí)了2018年新鮮出爐的React Hooks提案之后,針對異步請求數(shù)據(jù)寫的一個案例。注意,本文假設(shè)了:
1.你已經(jīng)初步了解hooks的含義了,如果不了解還請移步官方文檔。(其實有過翻譯的想法,不過印記中文一直在翻譯,就是比較慢啦)
2.你使用Redux實現(xiàn)過異步Action(非必需,只是本文不涉及該部分知識而直接使用)
3.你聽說過axios或者fetch(如果沒有,那么想象一下原生js的promise實現(xiàn)異步請求,或者去學(xué)習(xí)下這倆庫)
全部代碼參見倉庫: github | Marckon選擇hooks-onlineShop分支以及master分支查看
? 本文并非最佳實踐,如有更好的方法或發(fā)現(xiàn)文中紕漏,歡迎指正!
前序方案(不想看可以直接跳過)不考慮引入Redux
通過學(xué)習(xí)React生命周期,我們知道適合進(jìn)行異步請求的地方是componentDidMount鉤子函數(shù)內(nèi)。因此,當(dāng)你不需要考慮狀態(tài)管理時,以往的方法很簡單:
class App extends React.Component{ componentDidMount(){ axios.get("/your/api") .then(res=>/*...*/) } }
引入Redux進(jìn)行狀態(tài)管理
當(dāng)你決定使用Redux進(jìn)行狀態(tài)管理時,比如將異步獲取到的數(shù)據(jù)儲存在store中,事情就開始復(fù)雜起來了。根據(jù)Redux的官方文檔案例來看,為了實現(xiàn)異步action,你還得需要一個類似于redux-thunk的第三方庫來解析你的異步action。
requestAction.js: 定義異步請求action的地方
//這是一個異步action,分發(fā)了兩個同步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 () } }
GoodsList Component :需要進(jìn)行異步請求的組件
class GoodsList extends React.Component{ //... componentDidMount(){ this.props.fetchGoodsList("your/url"); } //... } const mapDispatchToProps={ fetchGoodsList } export default connect( mapStateToProps, mapDispatchToProps )(GoodsList);
完整代碼:branch:master-onlineShop
使用Hooks-useReducer()和useContext()總之使用Redux很累,當(dāng)然,你可以不使用Redux,直接通過props層層傳遞,或者使用context都可以。只不過本文我們學(xué)過了useReducer,使用到了Redux的思想,總要試著用一下。
這里你不需要引入別的任何第三方庫了,簡簡單單地使用[email protected]版本就好啦
很重要的一點就是——函數(shù)式組件,現(xiàn)在React推薦我們這么做,可以基本上代替class寫法。
函數(shù)簽名useReducer(reducer,initialState)
useContext(ctxObj)
useEffect(effectFunction,[dependencyValues])
概覽-你需要編寫什么
action.js:
我們還使用redux的思想,編寫action
reducer.js:
處理action,不同于redux的reducer,這里我們可以不用提供初始狀態(tài)
根組件:
Provider提供給子組件context
useReducer定義的位置,引入一個reducer并且提供初始狀態(tài)initialState
子組件:
useContext定義的位置,獲取祖先組件提供的context
useEffect用于進(jìn)行異步請求
實現(xiàn) 1.action.js:我們使用action創(chuàng)建函數(shù)const REQUEST_GOODSLIST = "REQUEST_GOODSLIST"; const RECEIVE_GOODSLIST = "RECEIVE_GOODSLIST"; //開始請求 const requestGoodsList = () => ({ type: REQUEST_GOODSLIST }); //接收到數(shù)據(jù) const receiveGoodsList = json => ({ type: RECEIVE_GOODSLIST, goodsList: json.goodsList, receivedAt: Date.now() }); export { RECEIVE_GOODSLIST, REQUEST_GOODSLIST, receiveGoodsList, requestGoodsList, }2.reducer.js:判斷action的類型并進(jìn)行相應(yīng)處理,更新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 ".."; //創(chuàng)建并export上下文 export const FetchesContext = React.createContext(null); function RootComponent() { //第二個參數(shù)為state的初始狀態(tài) const [fetchesState, fetchDispatch] = useReducer(fetchReducer, { isFetching: false, goodsList: [] }); return ( //將dispatch方法和狀態(tài)都作為context傳遞給子組件4.子組件:引入FetchesContext//... //用到context的一個子組件 ) }
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); //具有異步調(diào)用副作用的useEffect useEffect(() => { //首先分發(fā)一個開始異步獲取數(shù)據(jù)的action ctx.dispatch(requestGoodsList()); axios.get(proxyGoodsListAPI()) .then(res=>{ //獲取到數(shù)據(jù)后分發(fā)一個action,通知reducer更新狀態(tài) ctx.dispatch(receiveGoodsList(res.data)) }) //第二個參數(shù)reFetch指的是只有當(dāng)reFetch變量值改變才重新渲染 },[reFetch]); return ({ //children }) }
完整代碼參見:branch:hooks-onlineShop
目錄結(jié)構(gòu)我的目錄結(jié)構(gòu)大概這樣:
src |- actions |- fetchAction.js |- components |-... |- reducers |- fetchReducer.js |- index.js注意點
使用useContext()時候我們不需要使用Consumer了。但不要忘記export和import上下文對象
useEffect()可以看做是class寫法的componentDidMount、componentDidUpdate以及componentWillUnMount三個鉤子函數(shù)的組合。
當(dāng)返回了一個函數(shù)的時候,這個函數(shù)就在compnentWillUnMount生命周期調(diào)用
默認(rèn)地,傳給useEffect的第一個參數(shù)會在每次(包含第一次)數(shù)據(jù)更新時重新調(diào)用
當(dāng)給useEffect()傳入了第二個參數(shù)(數(shù)組類型)的時候,effect函數(shù)會在第一次渲染時調(diào)用,其余僅當(dāng)數(shù)組中的任一元素發(fā)生改變時才會調(diào)用。這相當(dāng)于我們控制了組件的update生命周期
useEffect()第二個數(shù)組為空則意味著僅在componentDidMount周期執(zhí)行一次
代碼倉庫里使用了Mock.js攔截api請求以及ant-design第三UI方庫。目前代碼比較簡陋。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99617.html
摘要:首發(fā)自我的博客,歡迎注如要運行本文的代碼,請先確認(rèn)自己的版本已支持出來已經(jīng)有段時間了,本文不對的具體用法作介紹,而是使用實現(xiàn)一個簡易的基于的使用實現(xiàn)初版自帶了供我們使用,它接受兩個參數(shù),一是函數(shù),二是初始,并返回和函數(shù),如下這個函數(shù)自己實現(xiàn) 首發(fā)自我的github博客,歡迎star 注:如要運行本文的代碼,請先確認(rèn)自己的react版本已支持hooks react hooks出來已經(jīng)有段...
摘要:比如就是一種,它可以用來管理狀態(tài)返回的結(jié)果是數(shù)組,數(shù)組的第一項是值,第二項是賦值函數(shù),函數(shù)的第一個參數(shù)就是默認(rèn)值,也支持回調(diào)函數(shù)。而之所以輸出還是正確的,原因是的回調(diào)函數(shù)中,值永遠(yuǎn)指向最新的值,因此沒有邏輯漏洞。 1. 引言 如果你在使用 React 16,可以嘗試 Function Component 風(fēng)格,享受更大的靈活性。但在嘗試之前,最好先閱讀本文,對 Function Com...
摘要:在線傳遞給的是而不是,返回值即是想要透傳的數(shù)據(jù)了。所以函數(shù)組件在每次渲染的時候如果有傳遞函數(shù)的話都會重渲染子組件。在學(xué)會使用React Hooks之前,可以先看一下相關(guān)原理學(xué)習(xí)React Hooks 前言 在 React 的世界中,有容器組件和 UI 組件之分,在 React Hooks 出現(xiàn)之前,UI 組件我們可以使用函數(shù),無狀態(tài)組件來展示 UI,而對于容器組件,函數(shù)組件就顯得無能為力,我...
摘要:當(dāng)組件安裝和更新時,回調(diào)函數(shù)都會被調(diào)用。好在為我們提供了第二個參數(shù),如果第二個參數(shù)傳入一個數(shù)組,僅當(dāng)重新渲染時數(shù)組中的值發(fā)生改變時,中的回調(diào)函數(shù)才會執(zhí)行。 前言 首先歡迎大家關(guān)注我的Github博客,也算是對我的一點鼓勵,畢竟寫東西沒法獲得變現(xiàn),能堅持下去也是靠的是自己的熱情和大家的鼓勵,希望大家多多關(guān)注呀!React 16.8中新增了Hooks特性,并且在React官方文檔中新增...
閱讀 871·2021-10-11 10:59
閱讀 2806·2019-08-30 15:43
閱讀 2136·2019-08-30 11:08
閱讀 1657·2019-08-29 15:20
閱讀 1016·2019-08-29 13:53
閱讀 493·2019-08-26 13:24
閱讀 1644·2019-08-26 13:24
閱讀 2828·2019-08-26 12:08