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

解決React中的re-render問題

 更新時(shí)間:2022年01月25日 17:14:10   作者:Peter?譚  
這篇文章主要介紹了解決React中的re-render問題,相信很多人都遇到過。接下來給大家具體講講這個(gè)問題,需要的朋友可以參考y一下,洗碗給對你有所幫助

文章轉(zhuǎn)自公眾號:前端巔峰

re-render?

首先使用我的腳手架:

npm i ykj-cli -g?
ykj init App
cd ./app
yarn?
yarn dev

這樣一個(gè)webpack5、TS、React項(xiàng)目就搭建好了

我們目前只有一個(gè)APP組件,內(nèi)部代碼:

import Myy from './myy.jpg';

function App() {
? ? console.log('render')
? ? return (
? ? ? ? <div className="app">
? ? ? ? ? ? <h1>歡迎使用明源云 - 云空間前端通用腳手架</h1>
? ? ? ? ? ? <img src={Myy} alt="" style={{ width: 500, height: 500 }} />
? ? ? ? ? ? <h4>
? ? ? ? ? ? ? ? 加入我們:<a>453089136@qq.com</a>
? ? ? ? ? ? </h4>
? ? ? ? ? ? <h4>微前端,webpack5,TypeScript,React,vite應(yīng)有盡有</h4>
? ? ? ? </div>
? ? );
}

export default App;

刷新訪問頁面后,發(fā)現(xiàn)控制臺只打印了一次

OK,那我們正式開始,加入一些狀態(tài),以及新增一個(gè)按鈕和SubApp組件

import { useState } from 'react';
import Myy from './myy.jpg';
import SubApp from './SubApp'
function App() {
? ? const [state, setState] = useState("Peter");
? ? return (
? ? ? ? <div className="app">
? ? ? ? ? ? <h1>歡迎使用明源云 - 云空間前端通用腳手架</h1>
? ? ? ? ? ? <img src={Myy} alt="" style={{ width: 500, height: 500 }} />
? ? ? ? ? ? <h4>
? ? ? ? ? ? ? ? 加入我們:<a>453089136@qq.com</a>
? ? ? ? ? ? </h4>
? ? ? ? ? ? <SubApp state={state} />
? ? ? ? ? ? <h4>微前端,webpack5,TypeScript,React,vite應(yīng)有盡有</h4>
? ? ? ? ? ? <button onClick={() => {
? ? ? ? ? ? ? ? setState('關(guān)注公眾號:前端巔峰')
? ? ? ? ? ? }}>測試按鈕</button>
? ? ? ? </div>
? ? );
}

export default App;


//SubApp組件
function SubApp({ state }) {
? ? console.log('render')
? ? return <h1>{state}</h1>
}

export default SubApp

這個(gè)時(shí)候點(diǎn)擊按鈕,又觸發(fā)了一次render

多次點(diǎn)擊,發(fā)現(xiàn)render只有一次,因?yàn)槲覀兇藭r(shí)每次點(diǎn)擊都是將state的值變成

那么,我們嘗試著將state變成一個(gè)對象

const [state, setState] = useState({ des: "Peter" });
? <button onClick={() => {
? ? ? ? ? ? ? ? setState({ des: '關(guān)注公眾號:前端巔峰' })
? ? ? ? ? ? }}>測試按鈕</button>

神奇的事情發(fā)生了,這里每次點(diǎn)擊設(shè)置同樣的state,都會觸發(fā)子組件render. - 這里就出現(xiàn)了re-render問題,我們其實(shí)都是拿的同樣的state,但是卻出現(xiàn)了不必要的render

錯(cuò)誤的優(yōu)化

很多同學(xué)在使用React過程中會錯(cuò)誤的使用PureComponentuseEffect以及UseMemo.

這里我們先用錯(cuò)誤的方式引入useEffect,改造SubApp

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

function SubApp({ state }) {
? ? const [data, setData] = useState({})
? ? useEffect(() => {
? ? ? ? console.log('render')
? ? ? ? setData(state)
? ? }, [state])
? ? console.log('render')
? ? return <h1>{data.des}</h1>
}

export default SubApp

這里可以看到,每次點(diǎn)擊按鈕都在不斷render,使用了useEffect竟然失效了。這優(yōu)化無效~

這里就要談到useEffect的源碼實(shí)現(xiàn),其實(shí)useEffectPureComponent等一系列優(yōu)化手段,大都是使用了Object.is()這個(gè)算法。

MDN資料地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is

Object.is

Object.is() 方法判斷兩個(gè)值是否為同一個(gè)值。

value1
被比較的第一個(gè)值。
value2
被比較的第二個(gè)值。
返回值
一個(gè) Boolean 類型標(biāo)示兩個(gè)參數(shù)是否是同一個(gè)值。

描述

Object.is() 方法判斷兩個(gè)值是否為同一個(gè)值。如果滿足以下條件則兩個(gè)值相等:

都是 undefined
都是 null
都是 true 或 false
都是相同長度的字符串且相同字符按相同順序排列
都是相同對象(意味著每個(gè)對象有同一個(gè)引用)
都是數(shù)字且
都是 +0
都是 -0
都是 NaN
或都是非零而且非 NaN 且為同一個(gè)值
與== (en-US) 運(yùn)算不同。== 運(yùn)算符在判斷相等前對兩邊的變量(如果它們不是同一類型) 進(jìn)行強(qiáng)制轉(zhuǎn)換 (這種行為的結(jié)果會將 "" == false 判斷為 true), 而 Object.is不會強(qiáng)制轉(zhuǎn)換兩邊的值。

與=== (en-US) 運(yùn)算也不相同。=== 運(yùn)算符 (也包括 == 運(yùn)算符) 將數(shù)字 -0 和 +0 視為相等 ,而將Number.NaN 與NaN視為不相等.

合理使用useEffect,解決re-render

如果Props傳入的是一個(gè)對象,那么由于React hooks每次更新都會生成一個(gè)全新的對象,而這個(gè)全新的對象和之前的對象,無法通過Object.is去對比,每次都會不相等。例如:

? const obj1 = {
? ? ? ? ? ? name: "peter"
? ? ? ? }
? ? ? ? const obj2 = {
? ? ? ? ? ? name: "peter"
? ? ? ? }

? ? ? ? console.log(Object.is(obj1, obj2, 'xx'))

這段代碼永遠(yuǎn)輸出都是false,因?yàn)閛bj1和obj2是兩個(gè)不同地址的引用對象

但是如果我們換一種方式:

Object.is(obj1.name, obj2.name )

這樣就可以正常比較,永遠(yuǎn)輸出ture了

那么我們現(xiàn)在也要在useEffect中類似這樣使用

? ? useEffect(() => {
? ? ? ? setData(state)
? ? ? ? console.log('render')
? ? }, [state.des])

這樣我們的useEffect內(nèi)部回調(diào)只會被觸發(fā)一次

簡單實(shí)現(xiàn)useEffect

網(wǎng)上抄的代碼改造了比較方法:

let _deps;
function useEffect(callback, dependencies) {
? const hasChanged = _deps
? ? && !dependencies.every((el, i) =>Object.is( el ,_deps[i]))
? ? || true;
? // 如果 dependencies 不存在,或者 dependencies 有變化,就執(zhí)行 callback
? if (!dependencies || hasChanged) {
? ? callback();
? ? _deps = dependencies;
? }
}

實(shí)現(xiàn)邏輯:將傳入的依賴項(xiàng)遍歷,通過Object.is方法與原依賴項(xiàng)的值進(jìn)行淺對比,如果不一致就執(zhí)行callback。

結(jié)語:
所以大家在解決re-render問題時(shí),或者使用useEffect之類優(yōu)化方案時(shí),應(yīng)該監(jiān)聽對比某個(gè)值,而不是去監(jiān)聽某個(gè)大對象進(jìn)行對比。相信這篇文章能解決你心中疑惑很久的re-render問題,

到此這篇關(guān)于解決React中的re-render問題的文章就介紹到這了,更多相關(guān)React中的re-render問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序 本地圖片按照屏幕尺寸處理

    微信小程序 本地圖片按照屏幕尺寸處理

    這篇文章主要介紹了微信小程序 本地圖片按照屏幕尺寸處理的相關(guān)資料,這里提供具體實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2017-08-08
  • 前端算法題解?leetcode50-Pow(x,?n)

    前端算法題解?leetcode50-Pow(x,?n)

    這篇文章主要為大家介紹了前端算法題解?leetcode50-Pow(x,?n)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • typeScript?泛型使用和泛型接口結(jié)合

    typeScript?泛型使用和泛型接口結(jié)合

    本篇文章主要介紹?typeScript?中新增的泛型概念、泛型使用、泛型與接口結(jié)合等內(nèi)容。具有一定的參價(jià)值,需要的小伙伴可以參考一下,希望對你有所幫助
    2022-02-02
  • 微信小程序使用navigateTo數(shù)據(jù)傳遞的實(shí)例

    微信小程序使用navigateTo數(shù)據(jù)傳遞的實(shí)例

    這篇文章主要介紹了微信小程序使用navigateTo數(shù)據(jù)傳遞的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • 微信小程序 數(shù)據(jù)訪問實(shí)例詳解

    微信小程序 數(shù)據(jù)訪問實(shí)例詳解

    這篇文章主要介紹了微信小程序 數(shù)據(jù)訪問實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 微信小程序(二十一)switch組件詳細(xì)介紹

    微信小程序(二十一)switch組件詳細(xì)介紹

    這篇文章主要介紹了微信小程序switch組件詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • javascript Number 與 Math對象的介紹

    javascript Number 與 Math對象的介紹

    這篇文章主要介紹了javascript Number 與 Math對象,文章圍繞 Number 與 Math對象的相關(guān)資料展開內(nèi)容,需要的朋友可以參考一下,希望對你有所幫助
    2021-11-11
  • lodash內(nèi)部方法getData和setData實(shí)例解析

    lodash內(nèi)部方法getData和setData實(shí)例解析

    本篇章我們將了解lodash里內(nèi)部關(guān)于Data的操作方法,重點(diǎn)關(guān)注getData、setData兩個(gè)內(nèi)部方法,同時(shí)由實(shí)現(xiàn)上引申其他內(nèi)部封裝的方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • js實(shí)現(xiàn)兔年轉(zhuǎn)圈圈動畫示例

    js實(shí)現(xiàn)兔年轉(zhuǎn)圈圈動畫示例

    這篇文章主要為大家介紹了js實(shí)現(xiàn)兔年轉(zhuǎn)圈圈動畫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 字節(jié)飛書面試promise.all實(shí)現(xiàn)示例

    字節(jié)飛書面試promise.all實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了字節(jié)飛書面試promise.all實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06

最新評論