ref hook之useRef

一、useRef

useRef函数:

1.一个参数:默认值

2.返回一个固定的对象(对象的地址是不会变化的),{current: 值}

javascript 复制代码
import React, { useState } from 'react'

export default function App() {
	const inpRef = React.createRef();
	const [n, setN] = useState(0);
	return (
		<div>
			<input ref={inpRef} type="text" />
			<button onClick={() => {
				console.log(inpRef.current)
			}}>得到input的值</button>

			<input type="number"
				value={n}
				onChange={e => {
					setN(e.target.value)
				}} />
		</div>
	)
}

如上代码,一旦我们input出发了onChange方法,导致组件重新渲染,那么每次就会重新创建inpRef,这对我们来说是完全没有必要的呀。我们希望,一个节点,一直使用一个ref。

推荐使用使用useRef替代createRef即可。

javascript 复制代码
mport React, { useState,useRef } from 'react'
window.arr =[];
export default function App() {
	const inpRef = useRef();
    window.arr.push(inpRef);
	const [n, setN] = useState(0);
	return (
		<div>
			<input ref={inpRef} type="text" />
			<button onClick={() => {
				console.log(inpRef.current)
			}}>得到input的值</button>

			<input type="number"
				value={n}
				onChange={e => {
					setN(e.target.value)
				}} />
		</div>
	)
}

arr中的对象都是相等的,保存的都是一个对象。

二、倒计时

同样的道理,我们每次启动的定时器应该都是同一个,而不是每次生成一个新的再清除。

最早我们是这样写的:

javascript 复制代码
import React, { useState, useEffect } from 'react'
let timer = null;
export default function App() {
	const [n, setN] = useState(10);
	useEffect(() => {//useEffect中使用setTimeInterval要注意,避免循环重复的问题
		if(n === 0){
			return;
		}
		timer = setTimeout(()=>{
			setN(n - 1)
		},1000)
		return () => {
			clearTimeout(timer);
		}
	}, [n])
	return (
		<div>
			<h1>{n}</h1>
		</div>
	)
}

上面的写法有个问题就是若当App这个函数组件被引用多次时,其中一个组件销毁,就会执行clearTimeout函数,对其他的组件有影响。最好的做法是组件节点之间互不影响。

javascript 复制代码
import React, { useRef, useState, useEffect } from 'react'

export default function App() {
	const [n, setN] = useState(10);
	const timerRef = useRef();// 这时保存的不是元素了,可以放置任意值
	useEffect(() => {//useEffect中使用setTimeInterval要注意,避免循环重复的问题
		if(n === 0){
			return;
		}
		timerRef.current = setTimeout(()=>{
			setN(n - 1)
		},1000)
		return () => {
			clearTimeout(timerRef.current);
		}
	}, [n])
	return (
		<div>
			<h1>{n}</h1>
		</div>
	)
}

若setTimerInterval解决呢?

javascript 复制代码
import React, { useState, useRef, useEffect } from 'react'
export default function App() {
    const [n, setN] = useState(10)
    const nRef = useRef(n); // {current:10}
    useEffect(() => {
        const timer = setInterval(() => {
            nRef.current--;
            setN(nRef.current);
            if(nRef.current === 0){
                clearInterval(timer);
            }
        }, 1000)
        return () => {
            clearInterval(timer);
        }
    }, [])
    return (
        <div>
            <h1>{n}</h1>
        </div>
    )
}

相当于实现了是跨越组件多次使用的是用一个对象。

相关推荐
谭光志11 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
Hilaku11 小时前
前端架构师的克制:什么时候该坚决对新技术说不?
前端·javascript·程序员
陈随易11 小时前
前端项目部署只要30秒
前端·后端·程序员
本末倒置18311 小时前
从 Vue CLI 迁移到 Rsbuild 后,JSX 突然全挂了?一次排查记录
前端
古夕11 小时前
多应用同域部署下 Favicon 异常问题排查与治理
前端·javascript
YIAN11 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp
Imchendiana11 小时前
《狂人日记NO.9》— 前后端一把梭,我的全栈实录
前端·后端
逍遥运德11 小时前
前端工程化-03:包管理NPM-package.json 和 package-lock.json 详解
前端·前端框架·前端工程化
逗逗豆巴吧11 小时前
WPS 加载项中实现当前文档直接上传
前端·javascript·ecmascript 6
慢功夫11 小时前
💡【调试】按下 F5 后,mini-vscode 到底做了什么
前端·visual studio code