国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

淺談React Hooks

yearsj / 1522人閱讀

摘要:另外也不利于組件的,及。所以在使用時,盡量將相關聯的,會共同變化的值放入一個。有同學可能會想,每次后都會執行,這樣會不會對性能造成影響。另外必須以開頭來命名,這樣工具才能正確檢測其是否符合規范。

</>復制代碼

  1. 由于工作的原因我已經很長時間沒接觸過React了。前段時間圈子里都在討論React Hooks,出于好奇也學習了一番,特此整理以加深理解。
緣由

在web應用無所不能的9012年,組成應用的Components也越來越復雜,冗長而難以復用的代碼給開發者們造成了很多麻煩。比如:

難以復用stateful的代碼,render props及HOC雖然解決了問題,但對組件的包裹改變了組件樹的層級,存在冗余;

在ComponentDidMount、ComponentDidUpdate、ComponentWillUnmount等生命周期中做獲取數據,訂閱/取消事件,操作ref等相互之間無關聯的操作,而把訂閱/取消這種相關聯的操作分開,降低了代碼的可讀性;

與其他語言中的class概念差異較大,需要對事件處理函數做bind操作,令人困擾。另外class也不利于組件的AOT compile,minify及hot loading。

在這種背景下,React在16.8.0引入了React Hooks。

特性

主要介紹state hook,effect hook及custom hook

State Hook

最基本的應用如下:

</>復制代碼

  1. import React, { useState } from "react"
  2. function counter() {
  3. const [count, setCount] = useState(0)
  4. return (
  5. You have clicked {count} times

  6. Click
  7. )
  8. }

調用useState,傳入初始值,通過數組的結構賦值得到獨立的local state count,及setCount。count可以理解為class component中的state,可見這里的state不局限于對象,可以為number,string,當然也可以是一個對象。而setCount可以理解為class component中的setState,不同的是setState會merge新老state,而hook中的set函數會直接替換,這就意味著如果state是對象時,每次set應該傳入所有屬性,而不能像class component那樣僅傳入變化的值。所以在使用useState時,盡量將相關聯的,會共同變化的值放入一個object。

再看看有多個“local state”的情況:

</>復制代碼

  1. import React, { useState } from "react"
  2. function person() {
  3. const [name, setName] = useState("simon")
  4. const [age, setAge] = useState(24)
  5. return (
  6. name: {name}

  7. age: {age}

  8. )
  9. }

我們知道當函數執行完畢,函數作用域內的變量都會銷毀,hooks中的state在component首次render后被React保留下來了。那么在下一次render時,React如何將這些保留的state與component中的local state對應起來呢。這里給出一個簡單版本的實現:

</>復制代碼

  1. const stateArr = []
  2. const setterArr = []
  3. let cursor = 0
  4. let isFirstRender = true
  5. function createStateSetter(cursor) {
  6. return state => {
  7. stateArr[cursor] = state
  8. }
  9. }
  10. function useState(initState) {
  11. if (isFirstRender) {
  12. stateArr.push(initState)
  13. setterArr.push(createStateSetter(cursor))
  14. isFirstRender = false
  15. }
  16. const state = stateArr[cursor]
  17. const setter = setterArr[cursor]
  18. cursor++
  19. return [state, setter]
  20. }

可以看出React需要保證多個hooks在component每次render的時候的執行順序都保持一致,否則就會出現錯誤。這也是React hooks rule中必須在top level使用hooks的由來——條件,遍歷等語句都有可能會改變hooks執行的順序。

Effect Hook

</>復制代碼

  1. import React, { useState, useEffect } from "react"
  2. function FriendStatus(props) {
  3. const [isOnline, setIsOnline] = useState(null)
  4. function handleStatusChange(status) {
  5. setIsOnline(status.isOnline)
  6. }
  7. // 基本寫法
  8. useEffect(() => {
  9. document.title = "Dom is ready"
  10. })
  11. // 需要取消操作的寫法
  12. useEffect(() => {
  13. ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange)
  14. return function cleanup() {
  15. ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange)
  16. }
  17. })
  18. if (isOnline === null) {
  19. return "Loading..."
  20. }
  21. return isOnline ? "Online" : "Offline"
  22. }

可以看到上面的代碼在傳入useEffect的函數(effect)中做了一些"side effect",在class component中我們通常會在componentDidMount,componentDidUpdate中去做這些事情。另外在class component中,需要在componentDidMount中訂閱,在componentWillUnmount中取消訂閱,這樣將一件事拆成兩件事做,不僅可讀性低,還容易產生bug:

</>復制代碼

  1. class FriendStatus extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = { isOnline: null };
  5. this.handleStatusChange = this.handleStatusChange.bind(this);
  6. }
  7. componentDidMount() {
  8. ChatAPI.subscribeToFriendStatus(
  9. this.props.friend.id,
  10. this.handleStatusChange
  11. );
  12. }
  13. componentWillUnmount() {
  14. ChatAPI.unsubscribeFromFriendStatus(
  15. this.props.friend.id,
  16. this.handleStatusChange
  17. );
  18. }
  19. handleStatusChange(status) {
  20. this.setState({
  21. isOnline: status.isOnline
  22. });
  23. }
  24. render() {
  25. if (this.state.isOnline === null) {
  26. return "Loading...";
  27. }
  28. return this.state.isOnline ? "Online" : "Offline";
  29. }
  30. }

如上代碼,如果props中的friend.id發生變化,則會導致訂閱和取消的id不一致,如需解決需要在componentDidUpdate中先取消訂閱舊的再訂閱新的,代碼非常冗余。而useEffect hook在這一點上是渾然天成的。另外effect函數在每次render時都是新創建的,這其實是有意而為之,因為這樣才能取得最新的state值。

有同學可能會想,每次render后都會執行effect,這樣會不會對性能造成影響。其實effect是在頁面渲染完成之后執行的,不會阻塞,而在effect中執行的操作往往不要求同步完成,除了少數如要獲取寬度或高度,這種情況需要使用其他的hook(useLayoutEffect),此處不做詳解。即使這樣,React也提供了控制的方法,及useEffect的第二個參數————一個數組,如果數組中的值不發生變化的話就跳過effect的執行:

</>復制代碼

  1. useEffect(() => {
  2. ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange)
  3. return () => {
  4. ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  5. }
  6. }, [props.friend.id])
Custom Hook

</>復制代碼

  1. A custom Hook is a JavaScript function whose name starts withuseand that may call other Hooks.

Custom Hook的使命是解決stateful logic復用的問題,如上面例子中的FriendStatus,在一個聊天應用中可能多個組件都需要知道好友的在線狀態,將FriendStatus抽象成這樣的hook:

</>復制代碼

  1. function useFriendStatus(friendID) {
  2. const [isOnline, setIsOnline] = useState(null);
  3. function handleStatusChange(status) {
  4. setIsOnline(status.isOnline);
  5. }
  6. useEffect(() => {
  7. ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
  8. return () => {
  9. ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
  10. };
  11. });
  12. return isOnline;
  13. }
  14. function FriendStatus(props) {
  15. const isOnline = useFriendStatus(props.friend.id)
  16. if (isOnline === null) {
  17. return "Loading..."
  18. }
  19. return isOnline ? "Online" : "Offline"
  20. }
  21. function FriendListItem(props) {
  22. const isOnline = useFriendStatus(props.friend.id)
  23. return (
  24. {props.friend.name}
  25. )
  26. }

FriendStatus和FriendListItem中的isOnline是獨立的,因custom hook復用的是stateful logic,而不是state本身。另外custom hook必須以use開頭來命名,這樣linter工具才能正確檢測其是否符合規范。

除了以上三種hook,React還提供了useContext, useReducer, useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect, useDebugValue內置hook,它們的用途可以參考官方文檔,這里我想多帶帶講講useRef。
顧名思義,這個hook應該跟ref相關的:

</>復制代碼

  1. function TextInputWithFocusButton() {
  2. const inputEl = useRef(null)
  3. const onButtonClick = () => {
  4. inputEl.current.focus()
  5. }
  6. return (
  7. <>
  8. )
  9. }

來看看官方文檔上的說明:

</>復制代碼

  1. useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

這句話告訴我們在組件的整個生命周期里,inputEl.current都是存在的,這擴展了useRef本身的用途,可以使用useRef維護類似于class component中實例屬性的變量:

</>復制代碼

  1. function Timer() {
  2. const intervalRef = useRef()
  3. useEffect(() => {
  4. const id = setInterval(() => {
  5. // ...
  6. })
  7. intervalRef.current = id
  8. return () => {
  9. clearInterval(intervalRef.current)
  10. }
  11. })
  12. // ...
  13. }

這在class component中是理所當然的,但不要忘記Timer僅僅是一個函數,函數執行完畢后函數作用域內的變量將會銷毀,所以這里需要使用useRef來保持這個timerId。類似的useRef還可以用來獲取preState:

</>復制代碼

  1. function Counter() {
  2. const [count, setCount] = useState(0)
  3. const prevCountRef = useRef()
  4. useEffect(() => {
  5. prevCountRef.current = count // 由于useEffect中的函數是在render完成之后異步執行的,所以在每次render時prevCountRef.current的值為上一次的count值
  6. })
  7. const prevCount = prevCountRef.current
  8. return

    Now: {count}, before: {prevCount}

  9. }
參考文章&拓展閱讀

React Hooks官方文檔

React hooks: not magic, just arrays

Why Isn’t X a Hook?

Making Sense of React Hooks

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102216.html

相關文章

  • 淺談reacthooks閉包陷阱

      本文不會過多講解基礎知識,更多說的是在使用useRef如何能擺脫 這個 閉包陷阱 ?  react hooks 的閉包陷阱 基本每個開發員都有遇見,這是很令人抓狂的。  (以下react示范demo,均為react 16.8.3 版本)  列一個具體的場景:  functionApp(){   const[count,setCount]=useState(1);   useEffect(()=...

    3403771864 評論0 收藏0
  • 淺談webpack之plugin,webpack-manifest-plugin源碼解讀

    摘要:注冊方法之后,當執行了當前的,那么掛載正在當前上的方法就會被執行。比如在開始編譯之前,就能觸發鉤子,就用到了當前的。上面都是前置知識,下面通過解讀一個源碼來鞏固下。先看一段簡單的源碼。,是眾多的的一個,官網的解釋是編譯創建之后,執行插件。 通過解讀webpack-manifest-plugin,了解下plugin機制 先簡單說一下這個插件的功能,生成一份資源清單的json文件,如下 s...

    william 評論0 收藏0
  • 淺談ReactFiber

    摘要:什么是每一個都有一個對應的,記錄這個節點的各種狀態,是一鏈表的結構的串聯起來。 1. 什么是fiber 每一個ReactElement都有一個對應的fiber, 記錄這個節點的各種狀態, fiber是一鏈表的結構的串聯起來。showImg(https://segmentfault.com/img/bVbqVZR?w=540&h=708); 2. Fiber的組成 export type...

    yibinnn 評論0 收藏0
  • 精讀《React Hooks

    摘要:更容易將組件的與狀態分離。也就是只提供狀態處理方法,不會持久化狀態。大體思路是利用共享一份數據,作為的數據源。精讀帶來的約定函數必須以命名開頭,因為這樣才方便做檢查,防止用判斷包裹語句。前端精讀幫你篩選靠譜的內容。 1 引言 React Hooks 是 React 16.7.0-alpha 版本推出的新特性,想嘗試的同學安裝此版本即可。 React Hooks 要解決的問題是狀態共享,...

    kohoh_ 評論0 收藏0
  • 新上課程推薦:《React Hooks 案例詳解(React 進階必備)》

    摘要:課程制作和案例制作都經過精心編排。對于開發者意義重大,希望對有需要的開發者有所幫助。是從提案轉為正式加入的新特性。并不需要用繼承,而是推薦用嵌套。大型項目中模塊化與功能解耦困難。從而更加易于復用和獨立測試。但使用會減少這種幾率。 showImg(https://segmentfault.com/img/bVbpNRZ?w=1920&h=1080); 講師簡介 曾任職中軟軍隊事業部,參與...

    Lin_YT 評論0 收藏0

發表評論

0條評論

yearsj

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<