在useState里面有过一定的解释
useRef
目的
- 如果你需要一个值,在组件不断render时保持不变
- 初始化:
const count = useRef(0) - 读取:
count.current
- 初始化:
- 为什么需要current?
- 为了保证两次useRef是同一个值(只有引用能做到)
- 和变更数据有关的hooks
useRef知识点合集
- 就是相当于全局作用域,一处被修改,其他地方全更新
const [count, setCount] = useState(0)
const countRef = useRef(0)
useEffect(() => {
console.log('use effect...',count)
const timer = setInterval(() => {
console.log('timer...count:', countRef.current)
setCount(++countRef.current)
}, 1000)
return ()=> clearInterval(timer)
},[])
- 普遍操作,用来操作dom
const Hook =()=>{
const [count, setCount] = useState(0)
const btnRef = useRef(null)
useEffect(() => {
console.log('use effect...')
const onClick = ()=>{
setCount(count+1)
}
btnRef.current.addEventListener('click',onClick, false)
return ()=> btnRef.current.removeEventListener('click',onClick, false)
},[count])
return(
<div>
<div>
{count}
</div>
<button ref={btnRef}>click me </button>
</div>
)
}
记得取消绑定事件!
return ()=> btnRef.current.removeEventListener('click',onClick, false)
具体解释
const refContainer = useRef(initialValue);
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
如果需要一个值,在组件不断render时保持不变,那就可以使用 useRef。
本质上,useRef 就像是可以在其 .current 属性中保存一个可变值的“盒子”。
我们改变的只是 refContainer.current 这个属性的值。refContainer 在每次渲染时的地址是不变的。useRef 会在每次渲染时返回同一个 ref 对象。
请记住,当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。只能自己手动渲染。比如在变更 .current 之后,再随便setState一个数据,这会使App再次执行。
useRef能做到有变化时自动render吗
- 答案
- 不能
- 因为不符合React的理念
- React的理念是UI=f(data)
- 如果你想要的这个功能自己添加
- 监听ref,当
ref.current变化时,调用setX即可
- 不想自己加就用Vue3
forwardRef
1. 函数组件无法接收ref的props
function App() {
const buttonRef = useRef(null);
return (
<div className="App">
<Button2 ref={buttonRef}>按钮</Button2>
</div>
);
}
const Button2 = props => {
console.log(props);
return <button className="red" {...props} />;
};
在App里 useRef 得到一个 buttonRef 对象,把它传给 Button2 组件,想让 buttonRef 引用到Button2对应的DOM对象。
可是控制台报错了,说函数组件不能接受refs的外部数据。打印出Button2的props,发现只有按钮被传进来了,ref没进来。外边虽然传了一个ref,但是一个函数组件找不到这个ref,读不到。
2. 使用 forwardRef传递ref
如果你的函数组件想要接受别人传来的ref参数,就必须把函数组件用 forwardRef 包起来。这样就可以接受ref作为第二个参数。不然就只有props这一个参数。forwardRef 会把别人传给你的ref帮你传进来。
const Button2=React.forwardRef((props,ref)=>{
console.log(props);
console.log(ref)
return <button className="red" ref={ref}/>;
})
打印ref,由于传进来的ref参数已经被绑定到了button元素的ref属性上,所以打印出来的 ref.current 就是button这个DOM节点。
类组件是不需要的,可以直接传。