react-hooks之useRef,useImperativeHandle的使用
1、函数内部使用
useRef可以用来做数据持久化,也可以用来获取到元素实例
ref.current的变化并不会导致函数组件的重新加载不像useState
可以用一个假的useState,结合useEffect的依赖让useRef的值改变后重新加载函数
import React, { useState, useContext, useRef, useEffect } from "react";
const App = () => {
const [num, setNum] = useState(0);
const myRef = useRef(0);
const btnRef = useRef();
useEffect(() => {
myRef.current += 1;
}, [num]);
return (
<div>
<h1>我是Ref:{myRef.current}</h1>
<button
ref={btnRef}
onClick={() => {
setNum((prev) => prev + 1);
console.log("button的文字: ", btnRef.current.innerText);//改变ref
}}
>
改变ref
</button>
</div>
);
};
export default App;
2、子组件使用
子组件使用不能直接<Child ref={childRef}><Child/>
这样子组件获取不到ref,要用forwordRef把子组件包裹起来传入两个参数(props,ref)
//父组件
import React, { useState, useContext, useRef, useEffect } from "react";
import Child from "./child";
const App = () => {
const [num, setNum] = useState(0);
const myRef = useRef(0);
const btnRef = useRef(null);
const childRef= useRef(null);
useEffect(() => {
myRef.current += 1;
}, [num]);
return (
<div>
<h1>我是Ref:{myRef.current}</h1>
<button
ref={btnRef}
onClick={() => {
setNum((prev) => prev + 1);
console.log("button的文字: ", btnRef.current.innerText);//改变ref
}}
>
改变ref
</button>
<Child ref={childRef}></Child>
</div>
);
};
export default App;
//子组件
import React, {useEffect, forwardRef } from "react";
const Child = forwardRef((props, ref) => {
console.log("props: ", props);
return (
<div ref={ref}>
<h1>我是子组件</h1>
<h1>{num}</h1>
</div>
);
});
export default Child;
3、useImperativeHandle
像父组件暴露子组件的实例(类似于子传父)
import { myContext } from "./store";
import React, { useState, useContext, useEffect, forwardRef, useImperativeHandle } from "react";
import GrandSon from "./grandSon";
const Child = forwardRef((props, ref) => {
const { setNum, num } = useContext(myContext);
const [name, setName] = useState("zs");
useImperativeHandle(ref, () => {
return { fn };
});
const fn = () => {
console.log("hahahha");
};
return (
<div ref={ref}>
<h1>我是子组件</h1>
<h1>{num}</h1>
<button
onClick={() => {
setNum((prev) => prev + 1);
setName("ls");
}}
>
子组件添加
</button>
<GrandSon num={num} name={name} />
</div>
);
});
export default Child;
子组件就能获取到暴露的值
//父组件
import React, { useState, useContext, useRef, useEffect } from "react";
import Child from "./child";
const App = () => {
const [num, setNum] = useState(0);
const myRef = useRef(0);
const btnRef = useRef();
const childRef= useRef(null);
useEffect(() => {
myRef.current += 1;
childRef.current?.fn?.();
}, [num]);
return (
<div>
<h1>我是Ref:{myRef.current}</h1>
<button
ref={btnRef}
onClick={() => {
setNum((prev) => prev + 1);
console.log("button的文字: ", btnRef.current.innerText);//改变ref
}}
>
改变ref
</button>
<Child ref={childRef}></Child>
</div>
);
};
export default App;