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