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