首頁 > 軟體

React 18中的state概念與使用、注意問題解決

2022-12-17 14:00:29

一、概念與基本使用

props中的所有屬性都是不可變的,這使得React元件不能隨著props的改變而改變。但在實際的開發中,我們更希望的是資料發生變化時,頁面也會隨著資料一起變化。React為我們提供了state用來解決這個問題。

state和props類似,都是一種儲存屬性的方式,但是不同點在於state只屬於當前元件,其他元件無法存取。並且state是可變的,當其發生變化後元件會自動重新渲染,以使變化在頁面中呈現。

在React中,當元件渲染完畢後,再修改元件中的變數,不會使元件重新渲染。
要使得元件可以收到變數的影響,必須在變數修改後對元件進行重新渲染。
這裡我們就需要一個特殊變數,當這個變數被修改時,元件會自動重新渲染。

state相當於一個變數,
只是這個變數在React中進行了註冊,
React會監控這個變數的變化,當state發生變化時,會自動觸發元件的重新渲染
使得我們的修改可以在頁面中呈現出來。

在函陣列件中,我們需要通過勾點函數,獲取state。

使用勾點 useState() 來建立state。

import {useState} from "react";

它需要一個值作為引數,這個值就是state的初始值
該函數會返回一個陣列

  • 陣列中第一個元素,是初始值
  • 初始值只用來顯示資料,直接修改不會觸發元件的重新渲染陣列中的第二個元素,是一個函數,通常會命名為setXxx
  • 這個函數用來修改state,呼叫其修改state後會觸發元件的重新渲染,並且使用函數中的值作為新的state值

現有如下元件Clock:

現在我們希望點選按鈕以後,時間可以重新整理直接顯示一個當前的最新日期。希望頁面重新渲染。但是,如果直接在clickHandler中修改date的值是無效的,像這樣:

在函數中使用state我們需要使用一種勾點(hook)函數。勾點函數可以在函陣列件中“勾出”React的特性,換句話說我們要用一個函數“勾出”state。

語法:

const [state, setState] = useState(initialState);

通過勾點函數useState()勾出state,useState()中需要傳遞一個初始值,這個值就是你希望在變數中儲存的值。
函數會返回一個陣列,陣列中有兩個元素,第一個元素是儲存了值的變數,第二個元素是一個函數用來對值進行修改。
比如上邊的案例,可以這樣修改:

使用useState()“勾出”的變數就是一個普通變數,它裡邊儲存了初始化的值,這個變數和其他變數沒什麼大區別,同樣修改這個變數的值也不會對元件產生實質性的影響,所以不要嘗試直接為state賦值。useState()“勾出”的函數用來修改state的值,他需要一個新的state值作為引數,呼叫後會觸發元件的重新渲染,從而使得頁面重新整理,在每次的重新渲染中都會使用新的state值作為引數。

二、注意問題

引出問題

有了state,使得React元件可以隨著某個值的改變而改變,我們無需再在某個值發生變化後重新手動對介面進行構建,React會替我們完成這些工作,大大降低了我們開發的難度。

但是state中還隱藏著一些不太容易發現的問題,現在假設我們需要開發一個計數器元件,這個元件非常簡單,有一個按鈕和一個數位,每點選一次按鈕數位就會增加1,大概長成這個樣子:

點選按鈕以後,數位就會增加1,這個元件的實現很簡單:

Counter.js

在clickHandler()中,我們呼叫了setCount(count+1)來對count進行更新,每次更新都是在前一次值的基礎上增加1。這個程式碼這麼寫在大部分的場景下都不會帶來任何的問題,但是在某些情況下就不一定了。

產生問題的原因

在React中我們通過setState()修改狀態都是非同步完成的,換句話說並不是呼叫完setState()後狀態立刻就發生變化,而是需要等上一段時間,當然這段時間不會很長。
像上邊的案例中state的修改雖然是非同步完成的,但是由於功能比較簡單,等待時間幾乎可以忽略不計。但隨著功能複雜度的提升,這個間隔會逐漸增多。

問題演示

假設呼叫setState()後1秒state的值才會真的改變,這時如果我們連續點選按鈕2次,第1次點選按鈕時count值是1,第2次點選速度比較快,從而兩次間隔沒有超過1秒,此時的count值依然是1,這就導致我點選了兩次按鈕,但是值只增加了1次,因為兩次count+1中的count都是1。

為了演示問題,可以將上述案例的setCount()放入到一個延時呼叫中:

這樣一來,點選按鈕後1秒setCount()才會呼叫,如果我們在1秒內點選按鈕多次,你會發現按鈕數值只會增加一次,很顯然我們不希望這種情況出現。

解決問題

要解決這個問題,其實也不難,在setState()時除了直接傳遞一個指定值以外,React還允許我們通過一個回撥函數來修改state,回撥函數的返回值就是新的state的值,使用回撥函數的好處是,這個回撥函數會確保上一次的setState()呼叫完成後才被呼叫,同時會使用最新的state值作為回撥函數的第一個引數。這樣一來就有效的避免了無法正確獲取上一個state值的問題。

上邊案例中的 setCount(count+1);可以改成這個樣子:

setCount(prevState => prevState+1);

這樣一來,函數中的prevState總是上次修改後的最新state,避免再次出現點選多次按鈕只修改一次的問題。總的來說,當我們修改一個state的值而需要依賴於前邊的值進行計算時,最安全的方式就是通過回撥函數而不是直接修改。

到此這篇關於React 18中的state概念與使用、注意問題的文章就介紹到這了,更多相關React state概念與使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com