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

需要避免的五個(gè)react的ref錯誤用法

 更新時(shí)間:2024年12月29日 08:38:10   作者:夕水  
react是一個(gè)優(yōu)秀的框架,提供了我們很多的便利,但是在使用的過程中,我們也會遇到很多的問題,其中一個(gè)就是ref的使用,以下是我列出的5個(gè)使用ref的錯誤用法,并提供了正確的用法,需要的朋友可以參考下

前言

react是一個(gè)優(yōu)秀的框架,提供了我們很多的便利,但是在使用的過程中,我們也會遇到很多的問題,其中一個(gè)就是ref的使用,以下是我列出的5個(gè)使用ref的錯誤用法,并提供了正確的用法。

錯誤1: 當(dāng)使用ref更好時(shí),卻使用state

一個(gè)常見的錯誤就是明明使用ref更合適管理狀態(tài)的時(shí)候,但是卻使用state來存儲狀態(tài)。例如存儲定時(shí)器的間隔時(shí)間。

錯誤用法: 我們將定時(shí)器間隔時(shí)間存儲在狀態(tài)中從而觸發(fā)了不必要的重新渲染。

import { useState, useEffect } from 'react';

export const CustomTimer = () => {
  const [intervalId, setIntervalId] = useState();
  const [time, setTime] = useState(new Date());
  useEffect(() => {
    const id = setInterval(() => {
      setTime(new Date());
    }, 1000);
    setIntervalId(id);
    return () => clearInterval(id);
  }, []);

  const stopTimer = () => {
    intervalId && clearInterval(intervalId);
  }

  return (
    <div>
      <p>{time.toLocaleString()}</p>
      <button onClick={stopTimer}>Stop Timer</button>
    </div>
  );
}

正確用法:將定時(shí)器間隔存儲在ref中,從而避免了不必要的重新渲染。

ref有個(gè)好處就是不會觸發(fā)組件的重新渲染,從而避免了不必要的性能問題。

import { useRef, useEffect } from'react';
 
export const CustomTimer = () => {
  const intervalIdRef = useRef();
  const [time, setTime] = useState(new Date());
  useEffect(() => {
    const id = setInterval(() => {
      setTime(new Date());
    }, 1000);
    intervalIdRef.current = id;
    return () => clearInterval(id);
  }, []);
  const stopTimer = () => {
    intervalIdRef.current && clearInterval(intervalIdRef.current);
  }
  return (
    <div>
      <p>{time.toLocaleString()}</p>
      <button onClick={stopTimer}>Stop Timer</button>
    </div>
  );
}

錯誤2: 在設(shè)置ref的值之前使用ref.current而不是ref

我們在使用ref傳遞值給某個(gè)函數(shù)或者子組件的時(shí)候,使用的是ref.current而不是ref本身,直接使用ref本身的情況下,ref本身就是一個(gè)變化的對象,我們可以在組件渲染時(shí)使用ref.current來獲取當(dāng)前的值,但是在設(shè)置ref的值之前,ref.current的值是undefined,這就會導(dǎo)致我們的代碼出現(xiàn)錯誤。

錯誤用法: 下面的代碼無法運(yùn)行,因?yàn)閞ef.current最初為空, 因此,當(dāng)代碼運(yùn)行時(shí),element為空。

import { useRef } from'react';

const useHovered = (element) => {
  const [hovered, setHovered] = useState(false);

  useEffect(() => {
    if(element === null) return;
      element.addEventListener('mouseenter', () => setHovered(true));
      element.addEventListener('mouseleave', () => setHovered(false));
    return () => {
        element.removeEventListener('mouseenter', () => setHovered(true));
        element.removeEventListener('mouseleave', () => setHovered(false));
    };
  }, [element]);

  return hovered;
}
export const CustomHoverDivElement = () => {
  const ref = useRef();
  const isHoverd = useHovered(ref.current);
  return (
    <div ref={ref}>
       Hoverd:{`${isHoverd}`}
    </div>
  );
}

正確用法: 我們需要在設(shè)置ref的值之前使用ref.current來獲取當(dāng)前的值。

import { useRef } from'react';
const useHovered = (ref) => {
  const [hovered, setHovered] = useState(false);
  useEffect(() => {
    if(ref.current === null) return;
      ref.current.addEventListener('mouseenter', () => setHovered(true));
      ref.current.addEventListener('mouseleave', () => setHovered(false));
    return () => {
        ref.current.removeEventListener('mouseenter', () => setHovered(true));
        ref.current.removeEventListener('mouseleave', () => setHovered(false));
    };
  }, [ref]);
  return hovered;
}
export const CustomHoverDivElement = () => {
  const ref = useRef();
  const isHoverd = useHovered(ref);
  return (
    <div ref={ref}>
      Hoverd:{`${isHoverd}`}
    </div>
  );
}

錯誤3: 忘記使用fowardRef

在初學(xué)react時(shí),我們可能都犯過這個(gè)錯誤,直接給組件傳遞ref參數(shù)。事實(shí)上,React 不允許你將 ref 傳遞給函數(shù)組件,除非它被forwardRef包裝起來。解決辦法是什么?只需將接收 ref 的組件包裝在 forwardRef 中,或?yàn)?ref prop 使用另一個(gè)名稱即可。

錯誤用法: 下面的代碼無法運(yùn)行,因?yàn)槲覀儧]有使用forwardRef來包裝組件。

import { useRef } from'react';
const CustomInput = ({ ref,...rest }) => {
    const [value, setValue] = useState('');
  useEffect(() => {
    if(ref.current === null) return;
    ref.current.focus();
  }, [ref]);
  return (
    <input ref={ref} {...rest} value={value} onChange={e => setValue(e.target.value)} />
  );
}
export const CustomInputElement = () => {
  const ref = useRef();
  return (
    <CustomInput ref={ref} />
  );
}

正確用法: 我們需要使用forwardRef來包裝組件。

import { useRef, forwardRef } from'react';
const CustomInput = forwardRef((props, ref) => {
  const [value, setValue] = useState('');
  useEffect(() => {
    if(ref.current === null) return;
    ref.current.focus();
  }, [ref]);
  return (
    <input ref={ref} {...props} value={value} onChange={e => setValue(e.target.value)} />
  );
})
export const CustomInputElement = () => {
  const ref = useRef();
  return (
    <CustomInput ref={ref} />
  );
}

錯誤4: 調(diào)用函數(shù)來初始化ref的值

當(dāng)你調(diào)用函數(shù)來設(shè)置 ref 的初始值時(shí),該函數(shù)將在每次渲染時(shí)被調(diào)用,如果該函數(shù)開銷很大,這將不必要地影響你的應(yīng)用性能。解決方案是什么?緩存該函數(shù)或在渲染期間初始化 ref(在檢查值尚未設(shè)置之后)。

錯誤用法: 下面的代碼很浪費(fèi)性能,因?yàn)槲覀冊诿看武秩緯r(shí)都調(diào)用了函數(shù)來設(shè)置 ref 的初始值。

import { useState, useRef, useEffect } from "react";

const useOnBeforeUnload = (callback) => {
  useEffect(() => {
    window.addEventListener("beforeunload", callback);
    return () => window.removeEventListener("beforeunload", callback);
  }, [callback]);
}

export const App = () => {
  const ref = useRef(window.localStorage.getItem("cache-date"));
  const [inputValue, setInputValue] = useState("");

  useOnBeforeUnload(() => {
    const date = new Date().toUTCString();
    console.log("Date", date);
    window.localStorage.setItem("cache-date", date);
  });

  return (
    <>
      <div>
        緩存的時(shí)間: <strong>{ref.current}</strong>
      </div>
      用戶名:{" "}
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
    </>
  );
}

正確用法: 我們需要緩存該函數(shù)或在渲染期間初始化 ref(在檢查值尚未設(shè)置之后)。

import { useState, useRef, useEffect } from "react";
const useOnBeforeUnload = (callback) => {
  useEffect(() => {
    window.addEventListener("beforeunload", callback);
    return () => window.removeEventListener("beforeunload", callback);
  }, [callback]);
}
export const App = () => {
  const ref = useRef(null);
  if (ref.current === null) {
    ref.current = window.localStorage.getItem("cache-date");
  }
  const [inputValue, setInputValue] = useState("");
  useOnBeforeUnload(() => {
    const date = new Date().toUTCString();
    console.log("Date", date);
    window.localStorage.setItem("cache-date", date);
  });

  return (
    <>
      <div>
        緩存的時(shí)間: <strong>{ref.current}</strong>
      </div>
      用戶名:{" "}
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
    </>
  );
}

錯誤5: 使用每次渲染都會改變的ref回調(diào)函數(shù)

ref 回調(diào)函數(shù)可以很好的管理你的代碼,但是,請注意,每當(dāng)更改時(shí),React 都會調(diào)用 ref 回調(diào)。這意味著當(dāng)組件重新渲染時(shí),前一個(gè)函數(shù)將使用 null 作為參數(shù)調(diào)用,而下一個(gè)函數(shù)將使用 DOM 節(jié)點(diǎn)調(diào)用。這可能會導(dǎo)致 UI 中出現(xiàn)一些不必要的閃爍。解決方案?確保緩存(使用useCallback) ref 回調(diào)函數(shù)。

錯誤用法: 下面的代碼無法正常工作,因?yàn)槊慨?dāng)inputValue或currentTime發(fā)生變化時(shí),ref 回調(diào)函數(shù)就會再次運(yùn)行,并且輸入將再次成為焦點(diǎn)。

import { useEffect, useState } from "react";

const useCurrentTime = () => {
  const [time, setTime] = useState(new Date());
  useEffect(() => {
    const intervalId = setInterval(() => {
      setTime(new Date());
    }, 1_000);
    return () => clearInterval(intervalId);
  });
  return time.toString();
}

export const App = () => {
  const ref = (node) => {
    node?.focus();
  };
  const [nameValue, setNameValue] = useState("");
  const currentTime = useCurrentTime();

  return (
    <>
      <h2>當(dāng)前時(shí)間: {currentTime}</h2>
      <label htmlFor="name">用戶名: </label>
      <input
        id="name"
        ref={ref}
        value={nameValue}
        onChange={(e) => setNameValue(e.target.value)}
      />
    </>
  );
}

正確用法: 我們需要確保緩存(使用useCallback) ref 回調(diào)函數(shù)。

import { useEffect, useState, useCallback } from "react";
const useCurrentTime = () => {
  const [time, setTime] = useState(new Date());
  useEffect(() => {
    const intervalId = setInterval(() => {
      setTime(new Date());
    }, 1_000);
    return () => clearInterval(intervalId);
  });
  return time.toString();
}
export const App = () => {
  const ref = useCallback((node) => {
    node?.focus();
  }, []);
  const [nameValue, setNameValue] = useState("");
  const currentTime = useCurrentTime();
  return (
    <>
      <h2>當(dāng)前時(shí)間: {currentTime}</h2>
      <label htmlFor="name">用戶名: </label>
      <input
        id="name"
        ref={ref}
        value={nameValue}
        onChange={(e) => setNameValue(e.target.value)}
      />
    </>
  );
}

以上就是需要避免的五個(gè)react的ref錯誤用法的詳細(xì)內(nèi)容,更多關(guān)于react的ref錯誤用法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Router添加路由攔截方法講解

    Router添加路由攔截方法講解

    在vue項(xiàng)目中使用vue-router做頁面跳轉(zhuǎn)時(shí),路由的方式有兩種,一種是靜態(tài)路由,另一種是動態(tài)路由。而要實(shí)現(xiàn)對路由的控制需要使用vuex和router全局守衛(wèi)進(jìn)行判斷攔截
    2023-03-03
  • React18新增特性介紹

    React18新增特性介紹

    react歷次版本迭代主要想解決的是兩類導(dǎo)致網(wǎng)頁卡頓的問題,分別是cpu密集型任務(wù)和io密集型任務(wù)導(dǎo)致的卡頓問題,react18新增特性就是為了解決上述問題
    2022-09-09
  • react?路由權(quán)限動態(tài)菜單方案配置react-router-auth-plus

    react?路由權(quán)限動態(tài)菜單方案配置react-router-auth-plus

    這篇文章主要為大家介紹了react路由權(quán)限動態(tài)菜單方案react-router-auth-plus傻瓜式配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • react+antd 遞歸實(shí)現(xiàn)樹狀目錄操作

    react+antd 遞歸實(shí)現(xiàn)樹狀目錄操作

    這篇文章主要介紹了react+antd 遞歸實(shí)現(xiàn)樹狀目錄操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • React項(xiàng)目中報(bào)錯:Parsing error: The keyword 'import' is reservedeslint的問題及解決方法

    React項(xiàng)目中報(bào)錯:Parsing error: The keyword &a

    ESLint 默認(rèn)使用的是 ES5 語法,如果你想使用 ES6 或者更新的語法,你需要在 ESLint 的配置文件如:.eslintrc.js等中設(shè)置 parserOptions,這篇文章主要介紹了React項(xiàng)目中報(bào)錯:Parsing error: The keyword 'import' is reservedeslint的問題及解決方法,需要的朋友可以參考下
    2023-12-12
  • 詳解React 條件渲染

    詳解React 條件渲染

    這篇文章主要介紹了React 條件渲染的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • react批量引入svg圖標(biāo)的方法

    react批量引入svg圖標(biāo)的方法

    這篇文章主要介紹了react批量引入svg圖標(biāo)的方法,在批量引入之前,我們需要安裝一個(gè)包并配置到typescript.json文件中,需要的朋友可以參考下
    2024-03-03
  • react中Suspense的使用詳解

    react中Suspense的使用詳解

    這篇文章主要介紹了react中Suspense的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • React?之?Suspense提出的背景及使用詳解

    React?之?Suspense提出的背景及使用詳解

    這篇文章主要為大家介紹了React?之?Suspense提出的背景及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • React使用Redux Toolkit的方法示例

    React使用Redux Toolkit的方法示例

    Redux Toolkit可以幫助開發(fā)者更快速、更高效地編寫Redux應(yīng)用,本文主要介紹了React使用Redux Toolkit的方法示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04

最新評論