一、useRef
useRef函数:
1.一个参数:默认值
2.返回一个固定的对象(对象的地址是不会变化的),{current: 值}
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即可。
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中的对象都是相等的,保存的都是一个对象。
二、倒计时
同样的道理,我们每次启动的定时器应该都是同一个,而不是每次生成一个新的再清除。
最早我们是这样写的:
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函数,对其他的组件有影响。最好的做法是组件节点之间互不影响。
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解决呢?
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>
)
}
相当于实现了是跨越组件多次使用的是用一个对象。