最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

react中使用usestate踩坑及解決

 更新時(shí)間:2022年08月05日 08:51:27   作者:可缺不可濫  
這篇文章主要介紹了react中使用usestate踩坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

usestate的常規(guī)用法

在react框架中,不適用類(lèi)組件,使用函數(shù)式組件又想自定義數(shù)據(jù)維護(hù)業(yè)務(wù)開(kāi)發(fā)的時(shí)候,就需要使用react提供的hook來(lái)完成。usestate就是最常見(jiàn)的一種hook。

const [name,setName] = useState('dx');
setName('dx1')

中括號(hào)實(shí)際是一個(gè)解構(gòu)運(yùn)算,第一個(gè)name是設(shè)置的值,第二個(gè)setName是只能用來(lái)改變name的方法。

useState遇到的坑

1、useState不適合復(fù)雜對(duì)象的更改

因?yàn)閡seState不能像setState那樣進(jìn)行合并更新,當(dāng)使用useState第二個(gè)參數(shù)進(jìn)行數(shù)據(jù)更新的時(shí)候,必須傳入一個(gè)完整的結(jié)構(gòu),而不僅僅只是改變的那一部分。

如果你想讓一個(gè)復(fù)雜的對(duì)象都能實(shí)現(xiàn)響應(yīng),可以分兩種情況。

第一種情況,這個(gè)復(fù)雜的對(duì)象每次都是整體發(fā)生改變,那么也可以直接使用useState。

第二種情況,你只是想讓許多的簡(jiǎn)單數(shù)據(jù)都放到一個(gè)對(duì)象里面,這樣便于統(tǒng)一管理,那我建議,如果這些簡(jiǎn)單數(shù)據(jù)之間都沒(méi)什么必然聯(lián)系的話(huà),還是分開(kāi)創(chuàng)建多個(gè)state更好。

在編碼的過(guò)程中,我們寧愿以空間復(fù)雜度換取時(shí)間復(fù)雜度,多創(chuàng)建幾個(gè)變量和創(chuàng)建一個(gè)變量,在用戶(hù)體驗(yàn)上并不會(huì)有太多的差別。

但如果數(shù)據(jù)過(guò)于復(fù)雜,diff算法找到對(duì)應(yīng)的變化及發(fā)生響應(yīng),大規(guī)模的重新渲染,這一過(guò)程,將會(huì)導(dǎo)致用戶(hù)體驗(yàn)下降。

2、useState異步回調(diào)的問(wèn)題

當(dāng)使用usestate對(duì)數(shù)據(jù)進(jìn)行更新,并不能立刻獲取到最新的數(shù)據(jù)。

? const [name, setName] = useState('dx');

? const handleTest = () => {
? ? console.log(name) // dx
? ? setName('dx1')
? ? console.log(name) // dx
? }

解決的辦法。

一、配合useEffect使用

? const [name, setName] = useState('dx');
? const handleTest = () => {
? ? console.log(name) //dx
? ? setName('dx1')
? ? console.log(name)//dx
? }
??
? useEffect(() => {
? ? console.log(name) //dx1
? },[name])

二、創(chuàng)建一個(gè)新的變量保存最新的數(shù)據(jù)

? const [name, setName] = useState('dx');
? const handleTest = () => {
? ? console.log(name) //dx
? ? const newName = "dx1"
? ? setName(newName)
? ? console.log(newName) //dx1
? }

三、用一個(gè)函數(shù)包裹,不推薦使用,因?yàn)楹瘮?shù)里面所有的東西都會(huì)全部重新定義

const [name, setName] = useState('dx');
 function text () {
   const handleTest = () => {
     console.log(name) //dx
     const newName = "dx1"
     setName(newName)
     console.log(name) //dx
     console.log(newName) //dx1
   }
   useEffect(() => {
     console.log(name) //dx1
   },[name])

   return (
     <div>
       {name} //點(diǎn)擊之前dx,點(diǎn)擊按鈕之后dx1
      <button type="button" onClick={handleTest }>改變名字</button>
     </div>
   )
 }
console.log(name) //點(diǎn)擊按鈕之前dx,點(diǎn)擊按鈕之后dx1

3、根據(jù)hook的規(guī)則,使用useState的位置有限制

強(qiáng)調(diào),所有的hook和自定義hook都遵循此規(guī)則。

僅頂層調(diào)用 Hook :不能在循環(huán),條件,嵌套函數(shù)等中調(diào)用useState()。

在多個(gè)useState()調(diào)用中,渲染之間的調(diào)用順序必須相同。

僅從React 函數(shù)調(diào)用 Hook:必須僅在函數(shù)組件或自定義鉤子內(nèi)部調(diào)用useState()。

4、使用useState,回調(diào)函數(shù)形式更改數(shù)據(jù)

const [a, setA] = useState({c:1})
/** oldA為之前的a,return為設(shè)置的新值 */
setA((oldA) => {
return {c: oldA.c + 1}
})

5、useState存入的值只是該值的引用(引用類(lèi)型)

const textObj = {name:'dx'}

const [useState1, setUseState1] = useState(textObj )

const [useState2, setUseState2] = useState(textObj )
/** usestate的操作不要放在函數(shù)的最外層,這里只是簡(jiǎn)單的代碼展示,你可以將set操作放在某個(gè)函數(shù)里面 */
setUseState1((oldUseState1) => {
	oldUseState1.age = 18
return {...oldUseState1}
})

useEffect(() => {
	/** 改變一個(gè)會(huì)導(dǎo)致兩個(gè)都改變,深淺拷貝的問(wèn)題 */
	console.log(useState1)  // {name: "dx", age: 18}
	console.log(useState2)  // {name: "dx", age: 18}
},[
useState1
])

解決的方案

const textObj = {name:'dx'}

const [useState1, setUseState1] = useState(textObj )

const [useState2, setUseState2] = useState(JSON.parse(JSON.stringify(textObj)))
/** usestate的操作不要放在函數(shù)的最外層,這里只是簡(jiǎn)單的代碼展示,你可以將set操作放在某個(gè)函數(shù)里面 */
setUseState1((oldUseState1) => {
	oldUseState1.age = 18
return {...oldUseState1}
})

useEffect(() => {
	/** 改變一個(gè)會(huì)導(dǎo)致兩個(gè)都改變,深淺拷貝的問(wèn)題 */
	console.log(useState1)  // {name: "dx", age: 18}
	console.log(useState2)  // {name: "dx"}
},[
useState1
])

6、useState,如果保存引用數(shù)據(jù),useEffect檢測(cè)不到變化?

const textObj = {name:'dx'}
const [useState1, setUseState1] = useState(textObj)
/** usestate的操作不要放在函數(shù)的最外層,這里只是簡(jiǎn)單的代碼展示,你可以將set操作放在某個(gè)函數(shù)里面 */
setUseState1((oldUseState1) => {
	oldUseState1.age = 18
return oldUseState1

useEffect(() => {
	console.log(useState1)  
},[
useState1
])
//結(jié)果是沒(méi)有任何反應(yīng)

解決方法

const textObj = {name:'dx'}
const [useState1, setUseState1] = useState(textObj)
/** usestate的操作不要放在函數(shù)的最外層,這里只是簡(jiǎn)單的代碼展示,你可以將set操作放在某個(gè)函數(shù)里面 */
setUseState1((oldUseState1) => {
	oldUseState1.age = 18
	/** 返回一個(gè)新的對(duì)象,useEffectc才能檢測(cè)得到 */
return {...oldUseState1}

useEffect(() => {
	console.log(useState1)  // {name: "dx", age: 18}
},[
useState1
])

7、useState無(wú)法保存一個(gè)函數(shù)

你是否嘗試著將函數(shù)的引用作為一個(gè)變量保存到useState中去呢?

比如:

  const testFunciton1 = () => {
    console.log({name: 'dx',age: '18'})
  }

  /** usestate保存函數(shù)測(cè)試 */
  const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1);

  useEffect(() => {
   console.log(stateFunction)
  }, [stateFunction])

打印結(jié)果

代碼中從未調(diào)用過(guò)testFunciton1 ,結(jié)果testFunciton1卻被執(zhí)行了

useEffect打印出來(lái)的卻是一個(gè)undefined。

稍微改動(dòng)一下代碼,再測(cè)試

  const testFunciton1 = () => {
    console.log({name: 'dx',age: '18'})
    return {
      name: 'yx',
      age: '17'
    }
  }

  /** usestate保存函數(shù)測(cè)試 */
  const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1);

  useEffect(() => {
   console.log(stateFunction)
  }, [stateFunction])

結(jié)果

很明顯,在useState中,函數(shù)會(huì)自動(dòng)調(diào)用,并且保存函數(shù)返回的值,而不能保存函數(shù)本身。

解決的方案

使用useState不能保存函數(shù),那么可以使用useCallback這個(gè)hook。

  /** useCallback,使用參數(shù)與useEffect一致 */
  const testFunction = useCallback(() => {
    // useCallback返回的函數(shù)在useCallbak中構(gòu)建
    const testFunciton1 = () => {
      console.log({ name: 'dx', age: '18' });
      return {
        name: 'yx',
        age: '17',
      };
    };
    return testFunciton1;
  }, []);

  useEffect(() => {
    console.log(testFunction());
  }, [testFunction]);

結(jié)果

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

前一段時(shí)間面試某大廠(chǎng)的時(shí)候,講到了useState這個(gè)hook,要求簡(jiǎn)單寫(xiě)一下useState的實(shí)現(xiàn)原理,以下代碼只是一個(gè)粗淺的原理。

function useState(init) {
	let state;
	// useState無(wú)法保存函數(shù)
	if(typeof init === 'function') {
		state = init()
	} else {
		state = init
	}

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • 一百多行代碼實(shí)現(xiàn)react拖拽hooks

    一百多行代碼實(shí)現(xiàn)react拖拽hooks

    這篇文章主要介紹了一百多行代碼實(shí)現(xiàn)react拖拽hooks,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • React虛擬渲染實(shí)現(xiàn)50個(gè)或者一百個(gè)圖表渲染

    React虛擬渲染實(shí)現(xiàn)50個(gè)或者一百個(gè)圖表渲染

    這篇文章主要為大家介紹了React虛擬渲染實(shí)現(xiàn)50個(gè)或者100個(gè)圖表渲染的實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • React封裝自定義Hook捕獲所有錯(cuò)誤的實(shí)現(xiàn)方法

    React封裝自定義Hook捕獲所有錯(cuò)誤的實(shí)現(xiàn)方法

    在 React 開(kāi)發(fā)中,錯(cuò)誤處理是確保應(yīng)用穩(wěn)定性和用戶(hù)體驗(yàn)的重要部分,React 提供了多種錯(cuò)誤捕獲方式,包括錯(cuò)誤邊界**等,本文將詳細(xì)介紹這些方法,并展示如何封裝一個(gè)能夠捕獲所有同步和異步錯(cuò)誤的自定義 Hook,需要的朋友可以參考下
    2024-12-12
  • React淺析Fragments使用方法

    React淺析Fragments使用方法

    這篇文章主要介紹了React Fragments使用方法,關(guān)于react Fragments,React中一個(gè)常見(jiàn)模式是為一個(gè)組件返回多個(gè)元素。Fragments 可以讓你聚合一個(gè)子元素列表,并且不在DOM中增加額外節(jié)點(diǎn)
    2022-12-12
  • 關(guān)于React Native使用axios進(jìn)行網(wǎng)絡(luò)請(qǐng)求的方法

    關(guān)于React Native使用axios進(jìn)行網(wǎng)絡(luò)請(qǐng)求的方法

    axios是一個(gè)基于Promise的Http網(wǎng)絡(luò)庫(kù),可運(yùn)行在瀏覽器端和Node.js中,Vue應(yīng)用的網(wǎng)絡(luò)請(qǐng)求基本都是使用它完成的。這篇文章主要介紹了React Native使用axios進(jìn)行網(wǎng)絡(luò)請(qǐng)求,需要的朋友可以參考下
    2021-08-08
  • 30分鐘帶你全面了解React Hooks

    30分鐘帶你全面了解React Hooks

    Hooks是一種函數(shù),該函數(shù)允許您從函數(shù)式組件 “勾住(hook into)”React狀態(tài)和生命周期功能。Hooks在類(lèi)內(nèi)部不起作用 - 它們?cè)试S你無(wú)需類(lèi)就使用 React。
    2021-05-05
  • forwardRef?中React父組件控制子組件的實(shí)現(xiàn)代碼

    forwardRef?中React父組件控制子組件的實(shí)現(xiàn)代碼

    forwardRef 用于拿到父組件傳入的 ref 屬性,這樣在父組件便能通過(guò) ref 控制子組件,這篇文章主要介紹了forwardRef?-?React父組件控制子組件的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2024-01-01
  • JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南

    JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南

    這篇文章主要介紹了JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南,React Web的目的即是把本地的React Native應(yīng)用程序項(xiàng)目變?yōu)閃eb應(yīng)用程序,需要的朋友可以參考下
    2016-05-05
  • React?component.forceUpdate()強(qiáng)制重新渲染方式

    React?component.forceUpdate()強(qiáng)制重新渲染方式

    這篇文章主要介紹了React?component.forceUpdate()強(qiáng)制重新渲染方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 淺談在react中如何實(shí)現(xiàn)掃碼槍輸入

    淺談在react中如何實(shí)現(xiàn)掃碼槍輸入

    這篇文章主要介紹了淺談在react中如何實(shí)現(xiàn)掃碼槍輸入,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07

最新評(píng)論

临汾市| 屏山县| 金堂县| 浦江县| 渝北区| 齐齐哈尔市| 柘城县| 玛沁县| 翁牛特旗| 临沭县| 眉山市| 富民县| 独山县| 阳山县| 饶平县| 吉林市| 定边县| 罗平县| 宜城市| 庆云县| 和硕县| 游戏| 基隆市| 澎湖县| 隆回县| 平顺县| 乐山市| 清苑县| 新泰市| 油尖旺区| 甘南县| 渝中区| 苏州市| 揭阳市| 井研县| 资讯 | 新密市| 天柱县| 湘潭县| 苍溪县| 台湾省|