React 回憶錄(四)React 中的狀態管理

Hi 各位,歡迎來到 React 回憶錄!👋 在上一章中,我介紹了使用 React 渲染界面元素的方法,以及在這個過程當中蘊含的「組件化」想一想。在本章中,咱們將把目光聚焦於 React 組件內部的狀態管理,去認識或從新思考如下三個核心概念:react

  1. propsstate
  2. 函數組件
  3. 類組件

讓咱們開始吧! 🙌數組

01. React 中的數據

站在「組件」的角度上,React 把應用中流動的數據分爲兩種類型:框架

  1. 不可更改內容,但能夠單向跨組件傳遞的 props
  2. 能夠更改內容,但不能跨組件傳遞的 state

進一步說,propsstate 的區別在於,props 是外部的,而且被任何渲染這個組件的代碼所控制。而 state 則是內部的,而且被組件自身所控制。函數

非計算機專業的初學者常常困惑 propsstate 在名稱與含義上的關聯,其實大可沒必要在乎,他們本質上只是 數據的別稱,只是在 React 中,它們被各自賦予了特殊的限制或能力。

你能夠經過組件上的 props 屬性,像在 HTML 中傳遞屬性同樣,將你想要傳遞的任何數據傳遞給子組件,全部的屬性都會被存儲在子組件(類組件)的 this.props 對象中。工具

function Parent(props) {
    return <Child name={"Tom"} />
}

function Child(props) {
    return <span>(props.name)</span>
}

02. 函數組件

咱們以前提到過,React 使用組件渲染視圖提高性能,而組件便是一個函數,能夠用一個公式來簡潔的表示其功用:f(數據) => UI。到這裏我想你應該注意到了,爲何咱們說 React 並非一個大型的 MVC (或 MVVM)框架,由於 React 只負責視圖層(View)的渲染,其餘的事情將由 React 生態中的其餘工具來完成。組件化

話說回來,對於 React 組件而言,最簡單的一種形式莫過於函數組件了,它充分展示了 React 的哲學,一次只作一件事組件化數據驅動UI性能

函數組件又稱爲「無狀態組件」,「受控組件」或「木偶組件」,由於函數組件只負責接收 props 並返回 UI,它自身並不能擁有可改變的數據,在真實的 React 應用開發場景下,咱們常常儘量的使用函數組件,將整個應用的 UI 拆分紅儘量小的視覺單元。this

這是由於函數組件是很是直觀的,它接收屬性返回元素,內部邏輯清晰明確,並且更重要的是,函數組件內沒有 this 關鍵字,所以你永遠不用擔憂煩人的「this上下文問題」。spa

記住:若是你的組件不須要追蹤內部狀態,儘可能使用函數組件。

03. 類組件

和函數組件相對應的,即是「類組件」了,相似的,它也被稱爲「有狀態組件」,「非受控組件」和「容器組件」。這裏須要注意,雖然咱們按照代碼的形式爲兩種類型的組件命名,但這並不嚴謹,由於在 JavaScript 中,「類」也是函數。設計

不一樣於函數組件,類組件擁有着能夠更改的內部數據 -- state。它最終影響着頁面的渲染狀況,並且 state 能夠被組件在任什麼時候刻在內部修改。一般的時刻時用戶與界面發生交互的時候。

因爲 React 把變化的數據封裝在組件內部,並堅持單向數據流的原則。咱們有了高度抽象的 UI 組件,並封裝複雜的業務邏輯。這使得咱們能夠經過構建,組合一系列小組件開發出大型應用。

那麼應該如何向類組件添加 state 呢?很簡單,咱們所要作的只是在類組件內部添加一個 state 屬性,state 屬性是一個對象。這個對象表明了組件的狀態,對象的每個屬性名都表明組件的一個特定的狀態,下面是具體的代碼:

import React from "react"

class Parent extends React.Component {
    state = {
        name: "Eliot",
    }
    
    render() {
        return <p>{this.state.name}</p>
    }
}

React 使咱們迫使大腦關注兩個重要的部分:

  1. 組件看起來是什麼樣?
  2. 組件當前的狀態是什麼?

經過讓組件管理本身的狀態,任什麼時候候狀態的變動都會令 React 自動更新相應的頁面部分。這即是使用 React 構建組件的主要優點之一:當頁面須要從新渲染時,咱們僅僅須要思考的是如何更改狀態。咱們沒必要跟蹤頁面的哪些部分須要更改,不須要決定如何有效的從新呈現頁面,React 自會比較先前的輸出和新的輸出,決定什麼應該發生改變,併爲咱們作出決定。而這個肯定以前改變了什麼和如今應該新輸出什麼的過程有一個專門的名詞,叫作 Reconciliation


04. 修改 state

你應該還記得類組件與函數組件最大的不一樣在於類組件自身擁有能夠改變內部數據的能力。那麼如何行使這一能力呢?和直覺不一樣,要作到這一點,你須要使用 React 提供的專門的 API:this.setState()

你有兩種方式使用該 API:

  1. 設置對象參數;
  2. 設置函數參數;

讓咱們先來看看第一種:

this.setState({
    name: "Tom"
})

React 會自動合併對 state 的改變。而有時,你的組件須要一個新的 state ,而這個 state 的變化又依賴於舊的 state 值,每當這種時候,你就該使用第二種 API 調用方式:

this.setState((prevState) => ({
    name: "mr." + prevState.name
}))

講到這裏你可能會感到奇怪,只是更新 state 而已,爲何還須要調用一個專門的 API?咱們直接修改以前定義的 state 對象不就行了嗎?之因此這樣設計的緣由是,組件內 state 的變化不只僅是對象屬性值發生變化那麼簡單,它還須要驅動整個 UI 進行從新渲染,所以 this.setState() 這個 API 被調用時實際上作了兩件事:

  1. 修改 state 對象;
  2. 驅動組件從新渲染;

若是你對 React 有必定研究,你可能會質疑我以上所羅列的兩點並不精確,的確如此,小小的 this.setState() API 其實內部還有不少細節值得注意,例如,當調用 this.setState() 時並不會當即改變 state 的值,也固然不會當即從新渲染組件。例如,當以對象爲參數調用 this.setState() API 時,儘管內部重複爲數據賦值,最終的數據也只保留最後一次更改的結果。

不過幸虧,這些略顯古怪的狀態早有前人爲咱們作了詳盡的解釋,若是你感興趣,請點擊下方連接查詢更多的信息:


05. 控制組件

當你在 Web 應用中使用表單時,這個表單的數據被存儲於相應的 DOM 節點內部,但正如咱們以前提到的,React 的整個關鍵點就在於如何高效的管理應用內的狀態。因此雖然表單的數據被存儲於 DOM 中,React 依然能夠對它進行狀態管理。

而管理的方式便是使用「控制組件」。簡單而言,「控制組件」會渲染出一個表單,可是將表單所需的全部真實數據做爲 state 存儲於組件內部,而不是 DOM 中。

之因此被稱爲「控制組件」的緣由也即在於此,「控制組件」控制着組件內的表單數據,所以,惟一更新表單數據的方式就是更新組件內部對應的 state 值。

import React as "react"

class Input extends React.Component {
    state = {
        value: "enter something...",
    }
    
    handleClick: (e) => {
        this.setState({value: e.target.value})
    }
    
    render() {
        <input value={this.state.value} onKeyup={this.handleClick} />
    }
}

能夠看到,咱們使用 handleClick 方法響應用戶每一次鍵盤敲擊以即時更新表單狀態,這樣作不只自然的支持了即時的輸入驗證,還容許你有條件的禁止或點亮表單按鈕。


06. 小結

這一章咱們介紹了 React 的兩種數據形式:stateprops,而且介紹了 React 組件的兩種形式:函數組件類組件,但願格外有所收穫,若是有任何問題或建議,也歡迎各位在評論區內留言,下一章見 🙌

PS:🔊若是你對該專題感興趣,別忘了訂閱本專欄,確保及時收到更新通知。記得點擊下方👇的各個按鈕,讓我知道你承認個人付出,這是激勵我持續產出的動力和源泉 😎。

相關文章
相關標籤/搜索