React Hooks瞭解一下?超簡單入門Hooks

前言

先簡單說一下Hooks是什麼,在寫React組件時候,有兩種寫法,一種是類寫法,一種就是函數寫法,Hooks主要服務的對象仍是函數組件,由於函數組件相對類組件有些功能確實很差實現,好比生命週期鉤子,Hooks就是讓函數組件具備類組件能力的一個東西,Hooks的出現會給咱們帶來另一種組件實現思路,一直看到有些小夥伴們問Hooks會不會代替Redux,emmm...我以爲這應該不是一個概念吧,這些小夥伴沒必要擔憂。javascript

Tips:按照慣例聲明,筆者也是入門級選手,所寫文章深度不會達到大佬的文章水平,只但願能對像我同樣的入門級小夥伴有所幫助。java

文字說明會很長,只有例子最明瞭

先來看一個能夠管理狀態的組件在React中怎樣寫react

import React from 'react'

class Counter extends React.Component {
    state = {
        count: 0
    }

    componentDidMount() {
        this.interval = setInterval(() => {
            this.setState({
                count: this.state.count + 1
            })
        }, 1000);
    }

    componentWillUnmount() {
        if(this.interval) {
            clearInterval(this.interval)
        }
    }

    render() {
        return (
            <div>count is : {this.state.count}</div>
        )
    }
}

export default Counter;
複製代碼

以上代碼寫了一個簡單的計數器組件,管理了一個count狀態(就是一個名字叫count的數據),在組件加載完成後,執行定時器,將count狀態每秒+1,在組件要被卸載以前清除定時器(不清除會一直佔用內存,可能致使內存泄漏)。這裏添加定時器和卸載定時器都是經過生命週期鉤子來實現的,在Hooks引入以前,函數組件沒法使用生命週期函數的,因此沒法完成上述的狀態管理功能。編程

引入Hooks,讓函數組件也能夠完成狀態管理redux

先簡單使用兩個Hooks,下文還會詳細介紹數組

import React, {useState, useEffect} from 'react'

function CounterFunc() {
    const [count, setCount] = useState(0)

    useEffect(() => {
        const interval = setInterval(() => {
            setCount(c => c + 1)
        },1000)

        return () => clearInterval(interval)
    },[])

    return (
        <div>count is : {count}</div>
    )
}

export default CounterFunc;
複製代碼

這裏直接上了一段代碼,在最開頭引入了兩個函數:useStateuseEffect閉包

在函數組件CounterFunc中,經過useState(0)來設置count的值,這裏useState(0)會返回一個數組,數組第一個元素就是被賦值爲0的變量,第二個元素是能夠對第一個元素從新設置值得函數。咱們這裏經過數組解構的方式,將這兩個元素分別賦值給countsetCount,(若是不瞭解ES6的解構賦值,請先查閱阮一峯老師ES6書籍的相關部分)。函數式編程

咱們還用了useEffect()函數,在函數裏定義了一個定時器,而後返回了一個函數,在返回的函數中清除了定時器,這個被返回的函數就至關於類組件中的componentWillUnmount()生命周子函數了。而這個useEffect()函數自己又至關於componentDidMount()生命週期函數。函數

至此咱們也能很輕鬆理解useState其實就至關於類組件中設置state的部分,它返回的數組第二個元素setCount()是一個高階函數,咱們須要傳入一個c => c + 1做爲參數,這個高階函數會將count傳進c => c + 1並將計算後的值從新賦值給count。 ui

State Hooks

useState()

對於狀態管理的Hooks,上面已經介紹了useState(),這裏會再加一個useReducer(),useReducer纔是基礎的狀態管理Hook

useState(0)

對useState傳遞的0只是對狀態設置了一個默認值,狀態改變後他就沒用了。

它返回的兩個元素我想你們應該也都清楚是什麼東西了,可是這裏要說的是第二個元素,它有兩種用法

  • setCount( 100 )傳遞一個肯定的值
  • setCount( c => c + 1)傳遞一個函數,咱們上面使用的方式

這裏說明一下咱們上面爲何不用setCount( count + 1 )的方式,有興趣的小夥伴能夠試試,這樣咱們頁面的結果始終都是1,而不是預期的1,2,3...... 爲何會發生這種事?這是因爲閉包形成的,在state更新後,會從新執行咱們建立的函數組件,這時候const [count, setCount] = useState(0)這段代碼會從新執行一遍,count每次都會被重置爲0,而後更新爲1。

閉包插曲:

上面說到了閉包,原本不想單獨說閉包,可是想了想,Hooks應該算是走函數式編程的道路吧,在學Hooks時候,咱們會遇到不少奇怪的現象,致使小夥伴感受很難,其實很大程度上跟沒掌握好閉包有很大關係。這裏就簡單說一下。

Tips: 請注意,若是你看別的文章從未搞懂過閉包,別擔憂,這裏我仍是有信心讓90%看我文章的人搞清楚什麼是閉包。有基礎的直接跳過!!!

要說閉包先說做用域

咱們這裏撇開let,const定義變量的方式,迴歸初心var 在JavaScript中,ES6出現以前是沒有塊級做用域的,可是它有個東西叫作函數做用域

var glob = '我是最外層定義的變量'

function func1() {
    console.log(glob) // 這裏能夠引用上層的變量
    var f1 = '我是func1中的變量'
    
    function func1_1() {
        var f1_1 = '我是函數func1_1中的變量'
        console.log(glob) 
        console.log(f1)  // 這裏能夠拿到上一層函數中定義的變量和最外層的變量
    }
    function func1_1() {
        console.log(glob) // 這裏能夠拿到最外層的變量
        console.log(f1_1) // 可是拿不到同一級別函數定義的變量
    }
    
}
複製代碼

上面這代碼和註釋相信能讓你們看懂一點JavaScript中的做用域。一個函數,是不能拿到同級別函數裏面定義的變量,可是能拿到父級,爺爺級,爺爺爺級函數定義的變量。咱們能夠利用這裏特性對變量進行封裝。

function func1(param) {
    var f1 = '只讓個人子孫拿到的變量‘
    var f2 = param; // 這裏把param賦值給f2,它也只能被本身子孫拿到
    
    function func1_1() {
        console.log(f1, f2) //都能拿到
    }
    
    return func1_1
}

console.log(f1, f2) //兩個都拿不到,報錯

var res1 = func1('hello') // 你猜他的結果是什麼。  

// 它的結果是一個函數,就是咱們返回的func1_1這個函數,猜錯的本身罰本身,給我點個贊,哈哈哈。

res1() // res1存放的就是返回的func1_1,因此再把它執行一遍 
//打印出 `只讓個人子孫拿到的變量hello`

複製代碼

其實在咱們執行func1('hello')以後,func1的生命週期就結束了,原本,它裏面定義的f1,f2都應該在它生命週期結束後就再也訪問不到了,可是幸運的是,func1_1替他保存下了這兩個變量,使得func1尚未死透

這樣封裝變量就是閉包。

閉包插曲結束

繼續上面的來講

咱們能夠經過setCount(c => c + 1)傳入回調函數的方式避免閉包帶來的奇怪現象。

useReducer

function countReducer(state, action) {
    switch(action.type) {
        case 'add': 
            return state + 1;
        case 'minus': 
            return state - 1;
        default:
            return state
    }
}

......
// const [count, setCount] = useState(0)
const [count, dispatchCount] = useReducer(countReducer,0);
......
// setCount(c => c + 1)
dispatchCount({ type: 'add' })
......
複製代碼

首先咱們先在CounterFunc外面定義一個reducer,而後更改count的定義,以及count的更新,這裏useReducer的使用跟 redux中操做很像,後面會持續更新Redux的使用,請有須要的小夥伴關注一下,順手給個贊。

要注意的是,useReducer(countReducer,0)的兩個參數,第一個是定義的countReducer第二個是默認值。咱們接收返回值的第二個元素固定寫爲dispach,或者這裏寫的dispachCount的格式。

小結

這裏主要分享了5個知識點,一個是函數組件與類組件的區別,一個是useState, 再一個useEffect(後面會詳細說),而後介紹了閉包,最後說明了useReducer的使用,相信認真看到這裏的小夥伴對於React的Hooks已經有了個初步瞭解,而且對閉包不熟悉的小夥伴也已經對閉包有了深刻認識吧。

相關文章
相關標籤/搜索