亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React useState超詳細(xì)講解用法

 更新時(shí)間:2022年11月28日 13:57:45   作者:YinJie…  
我正在處理的組件是表單的時(shí)間輸入。表單相對復(fù)雜,并且是動(dòng)態(tài)生成的,根據(jù)嵌套在其他數(shù)據(jù)中的數(shù)據(jù)顯示不同的字段。我正在用useReducer管理表單的狀態(tài),到目前為止效果很好

前言

React-hooks 正式發(fā)布以后, useState 可以使函數(shù)組件像類組件一樣擁有 state,也就說明函數(shù)組件可以通過 useState 改變 UI 視圖。那么 useState 到底應(yīng)該如何使用,底層又是怎么運(yùn)作的呢,首先一起看一下 useState 。

基本用法

[ state , dispatch ] = useState(initData)
  • state,目的提供給 UI ,作為渲染視圖的數(shù)據(jù)源。
  • dispatch 改變 state 的函數(shù),可以理解為推動(dòng)函數(shù)組件渲染的渲染函數(shù)。
  • initData 有兩種情況,第一種情況是非函數(shù),將作為 state 初始化的值。 第二種情況是函數(shù),函數(shù)的返回值作為 useState 初始化的值。

initData為非函數(shù)的情況

/* 此時(shí)將把 0 作為初使值 */const [ num , setNum ] = useState(0)

initData為函數(shù)的情況

每當(dāng) React 重新渲染組件時(shí),都會(huì)執(zhí)行useState(initData)。 如果初始狀態(tài)是原始值(數(shù)字,布爾值等),則不會(huì)有性能問題。

當(dāng)初始狀態(tài)需要昂貴的性能方面的操作時(shí),可以通過為useState(computeInitialState)提供一個(gè)函數(shù)來使用狀態(tài)的延遲初始化,如下所示:

function MyComponent({ bigJsonData }) {
  const [value, setValue] = useState(function getInitialData() {
    const object = JSON.parse(bigJsonData); 
    return object.initialValue;
  });
}

getInitialData()僅在初始渲染時(shí)執(zhí)行一次,以獲得初始狀態(tài)。在以后的組件渲染中,不會(huì)再調(diào)用getInitialData(),從而跳過昂貴的操作。

state變化監(jiān)聽

類組件 setState 中,有第二個(gè)參數(shù) callback 或者是生命周期 componentDidUpdat 可以檢測監(jiān)聽到 state 改變或是組件更新。

那么在函數(shù)組件中,如何怎么監(jiān)聽 state 變化呢?這個(gè)時(shí)候就需要 useEffect 出場了,通??梢园?state 作為依賴項(xiàng)傳入 useEffect 第二個(gè)參數(shù) deps ,但是注意 useEffect 初始化會(huì)默認(rèn)執(zhí)行一次。

具體可以參考如下 Demo :

import { useState, useEffect } from "react";
export default function App() {
  const [num, setNum] = useState(0);
  /* 監(jiān)聽 num 變化 */
  useEffect(() => {
    console.log("監(jiān)聽num變化,此時(shí)的num是:  " + num);
  }, [num]);
  const handerClick = () => {
    setNum(1);
    setTimeout(() => {
      setNum(3);
    });
  };
  console.log(num);
  return (
    <div>
      <span> {num}</span>
      <button onClick={handerClick}>num++</button>
    </div>
  );
}

點(diǎn)擊按鈕后輸出:

0
監(jiān)聽num變化,此時(shí)的num是:  0
1
監(jiān)聽num變化,此時(shí)的num是:  1
3
監(jiān)聽num變化,此時(shí)的num是:  3

我們再把上面的demo改成這樣,看看會(huì)輸出什么:

const [ num , setNum ] = React.useState(0)
const handleClick = ()=>{
    setNum(1) 
    console.log(num)
    setTimeout(()=>{
        setNum(3) 
        console.log(num)
    })   
}

結(jié)果:0 0 0

原因很簡單,函數(shù)組件更新就是函數(shù)的執(zhí)行,在函數(shù)一次執(zhí)行過程中,函數(shù)內(nèi)部所有變量重新聲明,所以改變的 state ,只有在下一次函數(shù)組件執(zhí)行時(shí)才會(huì)被更新。所以在如上同一個(gè)函數(shù)執(zhí)行上下文中,number 一直為0,無論怎么打印,都拿不到最新的 state 。

我們只需要記?。涸诒敬魏瘮?shù)執(zhí)行上下文中,是獲取不到最新的 state 值的就可以了

過時(shí)狀態(tài)問題

閉包是一個(gè)從外部作用域捕獲變量的函數(shù)。

閉包(例如事件處理程序,回調(diào))可能會(huì)從函數(shù)組件作用域中捕獲狀態(tài)變量。 由于狀態(tài)變量在渲染之間變化,因此閉包應(yīng)捕獲具有最新狀態(tài)值的變量。否則,如果閉包捕獲了過時(shí)的狀態(tài)值,則可能會(huì)遇到過時(shí)的狀態(tài)問題。

來看看一個(gè)過時(shí)的狀態(tài)是如何表現(xiàn)出來的。組件<DelayedCount>延遲3秒計(jì)數(shù)按鈕點(diǎn)擊的次數(shù)

import React, { useState } from 'react';
function DelayedCount() {
  const [count, setCount] = useState(0);
  const handleClickAsync = () => {
    setTimeout(function delay() {
      setCount(count + 1);
    }, 3000);
  }
  return (
    <div>
      {count}
      <button onClick={handleClickAsync}>Increase async</button>
    </div>
  );
}

快速多次點(diǎn)擊按鈕。count 變量不能正確記錄實(shí)際點(diǎn)擊次數(shù),有些點(diǎn)擊被吃掉。

delay() 是一個(gè)過時(shí)的閉包,它從初始渲染(使用0初始化時(shí))中捕獲了過時(shí)的count變量。

為了解決這個(gè)問題,使用函數(shù)方法來更新count狀態(tài):

import React, { useState } from 'react';
function DelayedCount() {
  const [count, setCount] = useState(0);
  const handleClickAsync = () => {
    setTimeout(function delay() {
      setCount(count => count + 1);
    }, 3000);
  }
  return (
    <div>
      {count}
      <button onClick={handleClickAsync}>Increase async</button>
    </div>
  );
}

現(xiàn)在setCount(count => count + 1)delay()中正確更新計(jì)數(shù)狀態(tài)。React 確保將最新狀態(tài)值作為參數(shù)提供給更新狀態(tài)函數(shù),過時(shí)閉包的問題解決了。

快速單擊按鈕。 延遲過去后,count 能正確表示點(diǎn)擊次數(shù)。

更新引用數(shù)據(jù)類型

在使用 useStatedispatchAction 更新 state 的時(shí)候,記得不要傳入相同的 state,這樣會(huì)使視圖不更新:

const textObj = {name:'yinjie'}
const [useState1, setUseState1] = useState(textObj)
setUseState1((oldUseState1) => {
	oldUseState1.name = 'xxx'
    return oldUseState1
}
useEffect(() => {
	console.log(useState1)  
},[useState1])
//結(jié)果是沒有任何反應(yīng)

為什么會(huì)造成這個(gè)原因呢?

useStatedispatchAction 處理邏輯中,會(huì)淺比較兩次 state ,發(fā)現(xiàn) state 相同,不會(huì)開啟更新調(diào)度任務(wù);demo 中兩次 state 指向了相同的內(nèi)存空間,所以默認(rèn)為 state 相等,就不會(huì)發(fā)生視圖更新了。

解決方法:

const textObj = {name:'yinjie'}
const [useState1, setUseState1] = useState(textObj)
setUseState1((oldUseState1) => {
	oldUseState1.name = 'xxx'
	/** 返回一個(gè)新的對象,useEffectc才能檢測得到 */
    return {...oldUseState1}
}
useEffect(() => {
	console.log(useState1)  // {name: "xxx"}
},[useState1])

在上面的 demo 中我們淺拷貝了對象,重新申請了一個(gè)內(nèi)存空間。

useState 實(shí)現(xiàn)原理

下面簡單寫一下useState的實(shí)現(xiàn)原理:

function useState(init) {
	let state;
	// useState無法保存函數(shù)
	if(typeof init === 'function') {
		state = init()
	} else {
		state = init
	}
	const setState = (change) => {
		// 判斷一下是否傳遞過來的是函數(shù)
		if(typeof change === 'function') {
			// 如果是函數(shù),調(diào)用,并將之前的state傳過去,接收到的返回值作為新的state并賦值
			state = change(state)
		} else {
			// 如果不是函數(shù),直接賦值
			state = change;
		}
	}	
	return [state, setState]
}

到此這篇關(guān)于React useState超詳細(xì)講解用法的文章就介紹到這了,更多相關(guān)React useState內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React Native中的RefreshContorl下拉刷新使用

    React Native中的RefreshContorl下拉刷新使用

    本篇文章主要介紹了React Native中的RefreshContorl下拉刷新使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • 使用React制作一個(gè)貪吃蛇游戲的代碼詳解

    使用React制作一個(gè)貪吃蛇游戲的代碼詳解

    Snake?Game?使用?ReactJS?項(xiàng)目實(shí)現(xiàn)功能組件并相應(yīng)地管理狀態(tài),開發(fā)的游戲允許用戶使用箭頭鍵控制蛇或觸摸屏幕上顯示的按鈕來收集食物并增長長度,本文給大家詳細(xì)講解了如何使用?React?制作一個(gè)貪吃蛇游戲,需要的朋友可以參考下
    2023-11-11
  • React Native提供自動(dòng)完成的下拉菜單的方法示例

    React Native提供自動(dòng)完成的下拉菜單的方法示例

    這篇文章主要為大家介紹了React Native提供自動(dòng)完成的下拉菜單的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 詳解如何使用Jest測試React組件

    詳解如何使用Jest測試React組件

    在本文中,我們將了解如何使用Jest(Facebook 維護(hù)的一個(gè)測試框架)來測試我們的React組件,我們將首先了解如何在純 JavaScript 函數(shù)上使用 Jest,然后再了解它提供的一些開箱即用的功能,這些功能專門用于使測試 React 應(yīng)用程序變得更容易,需要的朋友可以參考下
    2023-10-10
  • React UI組件庫ant-design的介紹與使用

    React UI組件庫ant-design的介紹與使用

    Ant Design是阿里螞蟻金服團(tuán)隊(duì)基于React開發(fā)的ui組件,主要用于中后臺系統(tǒng)的使用,這篇文章主要介紹了React UI組件庫ant-design的介紹與使用,需要的朋友可以參考下
    2023-12-12
  • React組件設(shè)計(jì)模式之組合組件應(yīng)用實(shí)例分析

    React組件設(shè)計(jì)模式之組合組件應(yīng)用實(shí)例分析

    這篇文章主要介紹了React組件設(shè)計(jì)模式之組合組件,結(jié)合實(shí)例形式分析了React組件設(shè)計(jì)模式中組合組件相關(guān)概念、原理、應(yīng)用場景與操作注意事項(xiàng),需要的朋友可以參考下
    2020-04-04
  • React組件的解耦技巧分享

    React組件的解耦技巧分享

    本文我們將和大家一起來研究如何有效地將組件解耦,讓我們的代碼變的復(fù)用性極高,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-11-11
  • React深入了解原理

    React深入了解原理

    React是用于構(gòu)建用戶界面的JavaScript庫,?[1]??起源于Facebook的內(nèi)部項(xiàng)目,該公司對市場上所有?JavaScript?MVC框架都不滿意,決定自行開發(fā)一套,用于架設(shè)Instagram的網(wǎng)站
    2022-07-07
  • React中使用Mobx的方法

    React中使用Mobx的方法

    Mobx是一個(gè)前端“狀態(tài)管理框架”,狀態(tài)管理就是將分布在各個(gè)組件、各個(gè)模塊中的狀態(tài)的變化,按照一定的規(guī)則,進(jìn)行統(tǒng)一的管理,這篇文章主要介紹了React中如何使用Mobx,需要的朋友可以參考下
    2023-02-02
  • react實(shí)現(xiàn)pure render時(shí)bind(this)隱患需注意!

    react實(shí)現(xiàn)pure render時(shí)bind(this)隱患需注意!

    這篇文章主要為大家詳細(xì)介紹了值得你在react實(shí)現(xiàn)pure render的時(shí)候,需要注意的bind(this)隱患,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03

最新評論