摘要:到目前為止,表達(dá)這種流程的基本形式是課程。按鈕依次響應(yīng)并更改獲取更新的文本。事實(shí)證明不能從返回一個(gè)。可以在組件中使用本地狀態(tài),而無(wú)需使用類。替換了提供統(tǒng)一,和。另一方面,跟蹤中的狀態(tài)變化確實(shí)很難。
備注:為了保證的可讀性,本文采用意譯而非直譯。
在這個(gè) React鉤子 教程中,你將學(xué)習(xí)如何使用 React鉤子,它們是什么,以及我們?yōu)槭裁催@樣做!
主要內(nèi)容你將學(xué)到什么
要求
項(xiàng)目設(shè)置
一開始有 setState
更新 React 中的狀態(tài),沒有 setState
開始時(shí)有 componentDidMount(和 render props)
使用 useEffect 獲取數(shù)據(jù)
可以使用 React 鉤子渲染嗎?
第一個(gè)自定義 React 鉤子
可以使用 async / await 和 useEffect 嗎?
結(jié)語(yǔ)
附錄
1、你將學(xué)到什么如何使用 React 鉤子
如何在 React 類組件中實(shí)現(xiàn)相同的邏輯
. 2、要求學(xué)習(xí)以下內(nèi)容,你應(yīng)該基本了解
ES6(箭頭函數(shù)、解構(gòu)、類)
React
3、項(xiàng)目設(shè)置這里默認(rèn)你已經(jīng)配置好 React 開發(fā)環(huán)境,我們?cè)囍惭b
npx create-react-app exploring-hooks4、一開始有 setState
假設(shè)你已經(jīng)在你的項(xiàng)目中使用了 React,讓我們快速回顧一下:
React 是一個(gè)用于構(gòu)建用戶界面的庫(kù),其優(yōu)點(diǎn)之一是庫(kù)本身會(huì)向開發(fā)人員強(qiáng)加嚴(yán)格的數(shù)據(jù)流。你還記得 jQuery 嗎?使用 jQuery,不太可能清楚地構(gòu)建項(xiàng)目,更不用說定義數(shù)據(jù)應(yīng)如何在 UI 中展示。這很難跟蹤哪些功能正在改變哪個(gè) UI 視圖。
這同樣適用于普通的 JavaScript:即使有自我解釋和實(shí)踐,也可以提出一個(gè)結(jié)構(gòu)良好的項(xiàng)目(考慮模塊模式),好的跟蹤狀態(tài)和功能之間的相互作用(請(qǐng)參閱 Redux )。
React 在某種程度上緩解了什么問題呢:通過強(qiáng)制執(zhí)行清晰的結(jié)構(gòu)(容器 和 功能組件) 和 嚴(yán)格的數(shù)據(jù)流(組件對(duì)狀態(tài) 和 道具更改 做出反應(yīng)),現(xiàn)在比以前更容易創(chuàng)建合理的 UI 視圖邏輯。
因此,React 理論上是,一個(gè) UI 可以 “ 響應(yīng) ” 以響應(yīng)狀態(tài)變化。到目前為止,表達(dá)這種流程的基本形式是 ES6 課程。考慮以下示例:從React.Component 擴(kuò)展的 ES6 類,具有內(nèi)部狀態(tài):
import React, { Component } from "react" export default class Button extends Component { constructor() { super(); this.state = { buttonText: "Click me, please" } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(() => { return { buttonText: "Thanks, been clicked!" } }); } render() { const { buttonText } = this.state return } }
從上面的代碼中可以看出,當(dāng)單擊按鈕時(shí),組件的內(nèi)部狀態(tài)會(huì)被 setState 改變。按鈕依次響應(yīng)并更改獲取更新的文本。
由于 類字段,刪除構(gòu)造函數(shù)可以表示更簡(jiǎn)潔的組件版本:
import React, { Component } from "react" export default class Button extends Component { state = { buttonText: "Click me, please" } handleClick = () => { this.setState(() => { return { buttonText: "Thanks, been clicked!" } }) }; render() { const { buttonText } = this.state return } }5、更新 React 中的狀態(tài),沒有 setState
那么我們現(xiàn)在有什么選擇來管理 React 中的內(nèi)部狀態(tài),是因?yàn)椴辉傩枰?setState 和 類 了嗎?
第一個(gè)也是最重要的 React 鉤子:useState。useState 是 react 暴露的函數(shù)。將在文件頂部引入它:
import React, { useState } from "react"
通過在代碼中導(dǎo)入 useState,在 React 組件中保存某種狀態(tài)的意圖。更重要的是,React 組件不再是 ES6 類。它可以是一個(gè)純粹而簡(jiǎn)單的 JavaScript 函數(shù)。
導(dǎo)入 useState 后,將選擇一個(gè)包含兩個(gè)變量的數(shù)組,這些變量不在 useState 中,代碼應(yīng)該放在 React 組件中:
const [buttonText, setButtonText] = useState("Click me, please")
如果對(duì)這種語(yǔ)法感到困惑,其實(shí)這是 ES6 解構(gòu)。上面的名字可以是你想要的任何東西,對(duì) React 來說無(wú)關(guān)緊要。
所以前面的例子,一個(gè)帶有鉤子的按鈕組件會(huì)變成:
import React, { useState } from "react" export default function Button() { const [buttonText, setButtonText] = useState("Click me, please") return ( ) }
要在 onClick 處理程序中調(diào)用 setButtonText 狀態(tài)更新程序,可以使用箭頭函數(shù)。但如果你更喜歡使用常見的功能,你可以:
import React, { useState } from "react" export default function Button() { const [buttonText, setButtonText] = useState("Click me, please") function handleClick() { return setButtonText("Thanks, been clicked!") } return }
除了有特殊要求外,我更喜歡常規(guī)功能而不是箭頭函數(shù)的方式。可讀性提高了很多。此外,當(dāng)我編寫代碼時(shí),我總是認(rèn)為下一個(gè)開發(fā)人員將保留代碼。這里的代碼應(yīng)該是可讀更強(qiáng)的。
6、開始時(shí)有 componentDidMount(和 render props)在 React 中獲取數(shù)據(jù)!你還記得 componentDidMount 嗎?你可以在 componentDidMount 中點(diǎn)擊提取(url)。以下是如何從 API 獲取數(shù)據(jù)以及如何展示為一個(gè)列表:
import React, { Component } from "react" export default class DataLoader extends Component { state = { data: [] } componentDidMount() { fetch("http://localhost:3001/links/") .then(response => response.json()) .then(data => this.setState(() => { return { data } }) ) } render() { return () } }{this.state.data.map(el => (
- {el.title}
))}
你甚至可以在 componentDidMount 中使用 async / await,但有一些注意事項(xiàng)。但是在項(xiàng)目中的大多數(shù)的異步邏輯都存在 React 組件之外。上面的代碼還有一些缺點(diǎn)。
渲染列表他是固定的,但使用渲染道具,我們可以輕松地將子項(xiàng)作為函數(shù)傳遞。重構(gòu)的組件如下所示:
import React, { Component } from "react" export default class DataLoader extends Component { state = { data: [] } componentDidMount() { fetch("http://localhost:3001/links/") .then(response => response.json()) .then(data => this.setState(() => { return { data } }) ) } render() { return this.props.render(this.state.data) } }
并且你將通過從外部提供渲染道具來使用當(dāng)前該組件:
7、使用 useEffect 獲取數(shù)據(jù){ return ( ) }} />{data.map(el => (
- {el.title}
))}
我認(rèn)為使用 React 鉤子獲取數(shù)據(jù)不應(yīng)該與 useState 有什么不同。工作中看文檔給了我一個(gè)提示:useEffect 可能是正確的一個(gè)工具。
當(dāng)看到:“ useEffect 與 React 類中的 componentDidMount,componentDidUpdate 和 componentWillUnmount 具有相同的用途時(shí),統(tǒng)一為單個(gè) API ”。
而且我可以使用 setData(從 useState 中提取的任意函數(shù))代替調(diào)用 this.setState:
import React, { useState, useEffect } from "react" export default function DataLoader() { const [data, setData] = useState([]) useEffect(() => { fetch("http://localhost:3001/links/") .then(response => response.json()) .then(data => setData(data)); }); return () }{data.map(el => (
- {el.title}
))}
在這一點(diǎn)上,我想“ 可能出現(xiàn)什么問題? ”,這是在控制臺(tái)中看到的:
這顯然是我的錯(cuò),因?yàn)槲乙呀?jīng)知道發(fā)生了什么:
“ useEffect 與 componentDidMount,componentDidUpdate 和 componentWillUnmount 具有相同的用途
componentDidUpdate!componentDidUpdate 是一個(gè)生命周期方法,每當(dāng)組件獲得新的道具或狀態(tài)發(fā)生變化時(shí)運(yùn)行。
這就是訣竅。如果你像我一樣調(diào)用 useEffect,你會(huì)看到無(wú)限循環(huán)。要解決這個(gè)“ bug ”,你需要傳遞一個(gè)空數(shù)組作為 useEffect 的第二個(gè)參數(shù):
// useEffect(() => { fetch("http://localhost:3001/links/") .then(response => response.json()) .then(data => setData(data)) }, []); // << super important array //8、可以使用 React 鉤子渲染嗎?
當(dāng)然!但是這樣做沒有意義。我們的 DataLoader 組件將會(huì)變?yōu)椋?/p>
import React, { useState, useEffect } from "react" export default function DataLoader(props) { const [data, setData] = useState([]) useEffect(() => { fetch("http://localhost:3001/links/") .then(response => response.json()) .then(data => setData(data)) }, []); // << super important array return props.render(data) }
并且你將通過從外部提供渲染道具來消耗組件,就像我們?cè)谇懊娴氖纠兴龅哪菢印?br>但同樣,這種重構(gòu)沒有意義,因?yàn)?React 鉤子的誕生是有原因的:在組件之間共享邏輯,我們將在下一節(jié)中看到一個(gè)例子。
9、第一個(gè)自定義 React 鉤子我們可以將我們的邏輯封裝在 React 鉤子中,然后在我們需要引入該鉤子時(shí),而不是 HO C和 渲染道具。在我們的示例中,我們可以創(chuàng)建用于獲取數(shù)據(jù)的自定義掛鉤。
根據(jù) React 文檔,自定義鉤子是一個(gè) JavaScript 函數(shù),其名稱以“ use ”開頭。比說起來容易。讓我們創(chuàng)建一個(gè) useFetch :
// useFetch.js import { useState, useEffect } from "react" export default function useFetch(url) { const [data, setData] = useState([]) useEffect(() => { fetch(url) .then(response => response.json()) .then(data => setData(data)) }, []); return data }
這就是你如何使用自定義鉤子:
import React from "react" import useFetch from "./useFetch" export default function DataLoader(props) { const data = useFetch("http://localhost:3001/links/") return () }{data.map(el => (
- {el.title}
))}
這就是使鉤子如此吸引人的原因:最后我們有一個(gè) 有趣的、標(biāo)準(zhǔn)化的、干凈 的方式來封裝和共享邏輯。
10、我可以使用 useEffect 的 async / await 嗎?當(dāng)你在使用 useEffect 時(shí)想在鉤子里嘗試 async / await。讓我們看看我們的自定義:
// useFetch.js import { useState, useEffect } from "react" export default function useFetch(url) { const [data, setData] = useState([]) useEffect(() => { fetch(url) .then(response => response.json()) .then(data => setData(data)) }, []) return data }
對(duì)于 重構(gòu)異步 / 等待 最自然的事情你可能會(huì):
// useFetch.js import { useState, useEffect } from "react" export default function useFetch(url) { const [data, setData] = useState([]) useEffect(async () => { const response = await fetch(url) const data = await response.json() setData(data) }, []) return data }
然后打開控制臺(tái),React 正在提示著:
“警告:不能返回任何內(nèi)容。
事實(shí)證明不能從 useEffect 返回一個(gè) Promise。JavaScript 異步函數(shù)總是返回一個(gè) promise,而 useEffect 應(yīng)該只返回另一個(gè)函數(shù),該函數(shù)用于清除效果。也就是說,如果你要在 useEffect 中啟動(dòng) setInterval,你將返回一個(gè)函數(shù)(我們有一個(gè)閉包)來清除間隔。
因此,為了使 React,我們可以像這樣重寫我們的異步邏輯:
// useFetch.js import { useState, useEffect } from "react" export default function useFetch(url) { const [data, setData] = useState([]) async function getData() { const response = await fetch(url) const data = await response.json() setData(data) } useEffect(() => { getData() }, []) return data }
這里,你的自定義鉤子將再次運(yùn)行。
11、結(jié)語(yǔ)React hooks 是庫(kù)的一個(gè)很好補(bǔ)充。他們于 2018年10月 作為 RFC 發(fā)布,很快就趕上了 React 16.8。將 React 鉤子想象為生活在 React 組件之外的封裝狀態(tài)。
React 鉤子使渲染道具和 HOC 幾乎過時(shí),并為共享邏輯提供了更好的人體工程學(xué)。使用 React 鉤子,你可以在 React 組件之間重用常見的邏輯片段。
React 附帶一堆預(yù)定義的鉤子。最重要的是 useState 和 useEffect。useState 可以在 React 組件中使用本地狀態(tài),而無(wú)需使用 ES6 類。
useEffec t替換了提供統(tǒng)一 API:componentDidMount,componentDidUpdate 和 componentWillUnmount。還有很多其他的鉤子,我建議閱讀官方文檔以了解更多信息。
很容易預(yù)見React的發(fā)展方向:功能組件遍布各處!但即便如此,我們還是有三種方法可以在 React 中表達(dá)組件:
功能組件
類組件
帶有掛鉤的功能組件
12、附錄在文章的開頭我說:“ 使用 jQuery,幾乎不可能清楚地構(gòu)建項(xiàng)目,更不用說定義數(shù)據(jù)應(yīng)如何在 UI 中展示”。
但是你可能不需要 React 來構(gòu)建用戶界面。有時(shí)我使用 vanilla JavaScript 構(gòu)建項(xiàng)目。當(dāng)我不確定該項(xiàng)目將采用什么形狀時(shí),我用來創(chuàng)建一個(gè)沒有任何 JavaScript 庫(kù)的簡(jiǎn)單原型。
在這些項(xiàng)目中,我依靠模塊的方式來編寫代碼。
能夠正確組織和編寫你的代碼,即使使用 vanilla JavaScript 也是每個(gè) JavaScript 開發(fā)人員的寶貴資產(chǎn)。為了更多地了解 JavaScript 中的模塊方式,我建議你由 Todd Motto 掌握模塊方式和 Addy Osmani 的 JavaScript 設(shè)計(jì)模式。
另一方面,跟蹤 UI 中的狀態(tài)變化確實(shí)很難。對(duì)于這種工作,我最喜歡的是 Redux,甚至可以使用 vanilla JavaScript。
備注:原文鏈接地址 https://www.valentinog.com/bl...文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105406.html
摘要:前言樓主最近在整理的一些資料,為項(xiàng)目重構(gòu)作準(zhǔn)備,下午整理成了這篇文章。給傳入的是一個(gè)初始值,比如,這個(gè)按鈕的最初要顯示的是。取代了提供了一個(gè)統(tǒng)一的。 showImg(https://segmentfault.com/img/bVbpUle?w=900&h=550); Hooks are a new addition in React 16.8. They let you use sta...
摘要:前言樓主最近在整理的一些資料,為項(xiàng)目重構(gòu)作準(zhǔn)備,下午整理成了這篇文章。給傳入的是一個(gè)初始值,比如,這個(gè)按鈕的最初要顯示的是。取代了提供了一個(gè)統(tǒng)一的。 showImg(https://segmentfault.com/img/bVbpUle?w=900&h=550); Hooks are a new addition in React 16.8. They let you use sta...
摘要:也可以安裝瀏覽器插件或,在某個(gè)文件的網(wǎng)頁(yè)上就能看到一個(gè)的按鈕,點(diǎn)擊即可。 【AIS-TXD前端技術(shù)月刊】- 本月熱門前端技術(shù)快報(bào),匯聚 Github Trending 流行 Repo 和熱門文章,文末有福利 showImg(https://segmentfault.com/img/remote/1460000018406928?w=1352&h=808); 歡迎?訂閱?&?投稿本期小編...
摘要:也可以安裝瀏覽器插件或,在某個(gè)文件的網(wǎng)頁(yè)上就能看到一個(gè)的按鈕,點(diǎn)擊即可。 【AIS-TXD前端技術(shù)月刊】- 本月熱門前端技術(shù)快報(bào),匯聚 Github Trending 流行 Repo 和熱門文章,文末有福利 showImg(https://segmentfault.com/img/remote/1460000018406928?w=1352&h=808); 歡迎?訂閱?&?投稿本期小編...
摘要:也可以安裝瀏覽器插件或,在某個(gè)文件的網(wǎng)頁(yè)上就能看到一個(gè)的按鈕,點(diǎn)擊即可。 【AIS-TXD前端技術(shù)月刊】- 本月熱門前端技術(shù)快報(bào),匯聚 Github Trending 流行 Repo 和熱門文章,文末有福利 showImg(https://segmentfault.com/img/remote/1460000018406928?w=1352&h=808); 歡迎?訂閱?&?投稿本期小編...
閱讀 2111·2021-11-24 10:28
閱讀 1114·2021-10-12 10:12
閱讀 3337·2021-09-22 15:21
閱讀 679·2021-08-30 09:44
閱讀 1895·2021-07-23 11:20
閱讀 1147·2019-08-30 15:56
閱讀 1751·2019-08-30 15:44
閱讀 1483·2019-08-30 13:55