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

react中useRef的使用和渲染機制

 更新時間:2025年11月21日 08:29:30   作者:暴走的皮卡丘  
本文主要介紹了react中useRef的使用和渲染機制,react useRef

前言

剛開始使用react時,由于對react的hook不太了解,導(dǎo)致在使用useState時,出現(xiàn)了閉包的問題,當時搜索解決方法時,發(fā)現(xiàn)了useRef這個hook可以很快的解決這個問題。這里用來記錄下自己對useRef這個hook的理解。

useRef的渲染機制

先要了解react中useRef和useState的區(qū)別,useState是用來管理組件狀態(tài)的,而useRef是用來管理組件引用的。useState會導(dǎo)致組件重新渲染,而useRef不會。對應(yīng)上面說的useRef解決閉包問題,其實不是react設(shè)置該hook的初衷,useRef這個hook的初衷是用來解決DOM操作問題的。能夠解決閉包問題也只是其副作用之一。對于useRef的渲染機制我們可以總結(jié)以下幾個關(guān)鍵點:

  • useRef在組件首次渲染時創(chuàng)建一個對象 { current: initialValue }
  • 整個組件的生命周期,不會創(chuàng)建新對象,返回的都是首次創(chuàng)建對象的引用
  • 無論如何賦值,都不會導(dǎo)致組件重新渲染(React通過Object.is比較檢測不到變化,因此不會觸發(fā)渲染)

以下是基于useRef的渲染機制的代碼示例,組件使用了antd的Button和Card組件,從代碼運行中我們可以看出,點擊更新Ref值按鈕,組件沒有重新渲染,但是點擊更新State值按鈕,組件會重新渲染。

import { Button, Card } from "antd";
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";

const DemoRef = () => {
    const ref = useRef<any>(null)
    // 渲染次數(shù)
    const renderCountRef = useRef(1);
    const renderValueRef = useRef<any>(0);
    const [renderValue, setRenderValue] = useState<any>(0);

    useEffect(() => {
        renderCountRef.current = renderCountRef.current + 1;
        console.log(`?? 組件第 ${renderCountRef.current + 1} 次渲染`);
    });

    return <div className="flex w-full">
        <Card title="useRef的渲染機制" className="ml-12px" hoverable={true}>
            <div className="mt-12px max-w-200px text-[#e74c3c] bg-[#fffacd] p-4 text-[18px] font-bold flex w-full flex-row w-400px">
                組件渲染此時:<span className="font-bold">{renderCountRef.current}</span>
            </div>
            <Button onClick={() => {
                renderValueRef.current = renderCountRef.current + 1;
            }} className="mt-12px">更新Ref值</Button>
            <div className="mt-12px font-bold mb-12px">當前Ref值:{renderValueRef.current}(點擊雖然新增了,但是組件沒有重新渲染,導(dǎo)致此處仍然時老的值)</div>
            <Button onClick={() => {
                setRenderValue((pre: number) => pre + 1);
            }}>更新State值</Button>
            <div className="mt-12px font-bold">當前State值:{renderValue}(點擊會觸發(fā)組件重新渲染,導(dǎo)致此處的值會更新)</div>
        </Card>

    </div>
}

useRef解決的問題

  • 解決閉包問題:useRef能夠在閉包函數(shù)中訪問到最新的狀態(tài)或?qū)傩允且驗?current屬性的引用不會改變。實際編碼中以下兩個場景會產(chǎn)生閉包,計時器顯示和事件函數(shù)監(jiān)聽,下面分享下useRef在這兩種場景的應(yīng)用

    • 計時器中使用最新的狀態(tài)或?qū)傩?/li>
    const [duration, setDuration] = useState(0);
    const durationRef = useRef(duration);
    useEffect(() => {
      const interval = setInterval(() => {
        durationRef.current = durationRef.current + 1;
        setDuration(durationRef.current);
      }, 1000);
      return () => clearInterval(interval);
    }, []);
    
    • 事件處理函數(shù)中使用最新的狀態(tài)或?qū)傩?,此處不再列舉代碼和說明,因為和計時器的場景類似。
  • react組件中DOM操作:useRef可以用來操作DOM元素,例如獲取輸入框的值、滾動到指定位置等。 const inputRef = useRef(null); const handleClick = () => { inputRef.current.focus(); };

  • 解決性能問題,方便避免重復(fù)創(chuàng)建ref的內(nèi)容

useRef的好兄弟forwardRef

在日常的開發(fā)中,多層組件嵌套是常有的場景,例如父組件中嵌套子組件,子組件中又嵌套孫子組件等。在這種場景下,我們偶爾會需要在父組件中操作子組件的DOM。這時候,如果直接在子組件上使用useRef,會獲取不到子組件的DOM并且控制還會報錯,原因是react為了保證組件的封裝性,默認情況下自定義的組件是不會暴漏其內(nèi)部DOM節(jié)點的ref,具體錯誤大家可以自己試試。報錯提示中會提示我們在子組件中需要使用forwardRef來轉(zhuǎn)發(fā)ref。

  • 以下是基于forwardRef的代碼示例,從代碼運行中我們可以看出,點擊設(shè)置子組件的年齡為18按鈕,子組件的年齡會更新為18。
  • 使用方式:子組件使用forwardRef包裹,需要轉(zhuǎn)發(fā)的方式使用useImperativeHandle
import { Button, Card } from "antd";
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";

const LoginForm = forwardRef((props: any, ref: React.ForwardedRef<{ reset: (flag: boolean) => void; }>) => {
    const { name } = props;
    const [formData, setFormData] = useState({
        username: '',
        password: ''
    });
    useImperativeHandle(ref, () => ({
        // 重置表單內(nèi)容
        reset: () => {
            setFormData({
                username: '',
                password: ''
            })
        },
    }));
    return <div className="mt-12px font-bold">
        <h2>{name}</h2>
        <div>
            <div className="mt-12px">
                用戶名:<Input type="text" value={formData.username} onChange={(e) => {
                    setFormData({
                        ...formData,
                        username: e.target.value
                    })
                }} />
            </div>
            <div className="mt-12px">
                密碼:<Input type="password" value={formData.password} onChange={(e) => {
                    setFormData({
                        ...formData,
                        password: e.target.value
                    })
                }} />
            </div>
        </div>
    </div>
})
//父組件
  <Card title="useRef和useForwardRef的組合" className="ml-12px" hoverable={true}>
            <Button onClick={() => {
                childRef.current?.reset();
            }} type="primary">重置</Button>
            <Divider></Divider>
            <LoginForm name="登錄表單" ref={childRef} />
        </Card>
  • forwardsRef注意點
    • forwardsRef和useRef組合很方便操作子組件的DOM,但是我們盡量避免在父組件中直接操作子組件的DOM,因為這會破壞組件的封裝性,導(dǎo)致代碼難以維護。
    • forwardsRef和useRef組合通過useImperativeHandle轉(zhuǎn)發(fā)的方法,我們可以在父組件中控制子組件的狀態(tài),但是如非必要此種也盡量少用,優(yōu)先用 useState + props 傳遞狀態(tài)(如父組件通過 isVisible props 控制子組件彈窗),而非用 ref 調(diào)用方法(ref 僅用于 “必須操作 DOM / 內(nèi)部方法” 的場景)

到此這篇關(guān)于react中useRef的使用和渲染機制的文章就介紹到這了,更多相關(guān)react useRef使用和渲染內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React合成事件詳解

    React合成事件詳解

    這篇文章主要介紹了React合成事件的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-05-05
  • 高性能React開發(fā)React Server Components詳解

    高性能React開發(fā)React Server Components詳解

    ReactServerComponents通過服務(wù)器端渲染、自動代碼分割等技術(shù),實現(xiàn)了高性能的React開發(fā),它解決了客戶端數(shù)據(jù)請求鏈式延遲、敏感數(shù)據(jù)暴露風(fēng)險等問題,提供了更好的用戶體驗和安全性,本文介紹高性能React開發(fā)React Server Components詳解,感興趣的朋友一起看看吧
    2025-03-03
  • React性能優(yōu)化三劍客之useMemo、memo與useCallback詳解

    React性能優(yōu)化三劍客之useMemo、memo與useCallback詳解

    useMemo和useCallback是React 中用于性能優(yōu)化的兩個重要 Hook,它們基于相同的依賴項比較機制,但適用場景不同,這篇文章主要介紹了React性能優(yōu)化三劍客之useMemo、memo與useCallback的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • React + Redux 從單向數(shù)據(jù)流到閉環(huán)實現(xiàn)

    React + Redux 從單向數(shù)據(jù)流到閉環(huán)實現(xiàn)

    本文徹底剖析 React、Redux 及 Store、Action、Reducer 之間的邏輯關(guān)系與實現(xiàn)原理,構(gòu)建一個完整的“數(shù)據(jù)流閉環(huán)”認知模型,感興趣的可以了解一下
    2026-06-06
  • React中不適當?shù)腍ooks使用問題及解決方案

    React中不適當?shù)腍ooks使用問題及解決方案

    在 React 開發(fā)中,Hooks 提供了一種強大的方式來管理組件的狀態(tài)和生命周期,然而,不恰當?shù)?nbsp;Hooks 使用可能會導(dǎo)致組件行為異常、性能問題或難以調(diào)試的錯誤,本文將探討 React 中常見的不適當 Hooks 使用問題,并提供解決方案,需要的朋友可以參考下
    2025-03-03
  • react?express實現(xiàn)webssh?demo解析

    react?express實現(xiàn)webssh?demo解析

    這篇文章主要為大家介紹了詳解react?express實現(xiàn)webssh?demo解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • React RenderProps模式運用過程淺析

    React RenderProps模式運用過程淺析

    render props是指一種在 React 組件之間使用一個值為函數(shù)的 prop 共享代碼的技術(shù)。簡單來說,給一個組件傳入一個prop,這個props是一個函數(shù),函數(shù)的作用是用來告訴這個組件需要渲染什么內(nèi)容,那么這個prop就成為render prop
    2023-03-03
  • useReducer?createContext代替Redux原理示例解析

    useReducer?createContext代替Redux原理示例解析

    這篇文章主要為大家介紹了useReducer?createContext代替Redux原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • 在React中讓編譯器生成生產(chǎn)環(huán)境版本的完整指南

    在React中讓編譯器生成生產(chǎn)環(huán)境版本的完整指南

    本文將詳細介紹如何在 React 項目中配置和生成生產(chǎn)環(huán)境版本,包括多種方法和最佳實踐,并通過代碼示例講解的非常詳細,需要的朋友可以參考下
    2025-09-09
  • React引入antd-mobile+postcss搭建移動端

    React引入antd-mobile+postcss搭建移動端

    本文給大家分享React引入antd-mobile+postcss搭建移動端的詳細流程,文末給大家分享我的一些經(jīng)驗記錄使用antd-mobile時發(fā)現(xiàn)我之前配置的postcss失效了,防止大家踩坑,特此把解決方案分享到腳本之家平臺,需要的朋友參考下吧
    2021-06-06

最新評論

海淀区| 金沙县| 辉南县| 偃师市| 潜江市| 南江县| 甘谷县| 南平市| 伽师县| 铅山县| 高雄市| 海林市| 湖口县| 梁平县| 台南县| 宝应县| 抚顺县| 海安县| 通州区| 二连浩特市| 陆河县| 蕲春县| 江津市| 绍兴县| 贺兰县| 白山市| 潼南县| 天长市| 岗巴县| 宁明县| 阜城县| 秭归县| 龙泉市| 于田县| 淳安县| 北海市| 和龙市| 江安县| 甘肃省| 宜城市| 岳普湖县|