大概分享一下两种常见情况下,使用useref。
第一种,同一组件内部,通过useref来获取某一个dom标签以及dom标签的方法。
在以前使用ref的时候,我们经常用ref来保存某个需要的dom标签,这样需要用到的时候,就可以不用去寻找这个dom标签了,在js中,通过方法,parentNode,lastchild,nextElementsibling 这种关系结构来找dom是一件比较麻烦的事情。如果不是动态类名或者id的话,通过document.getElementsByClassName 之类的方法,虽然可行,却也比较麻烦,因为得到的是一个dom数组。
看看useref如何实现
import React, {
useState, useEffect, useMemo, useRef } from 'react';
export default function App(props){
const [count, setCount] = useState(0);
const doubleCount = useMemo(() => {
return 2 * count;
}, [count]);
const couterRef = useRef(); //创建useRef
useEffect(() => {
document.title = `The value is ${
count}`;
//通过couterRef 的current 属性可以获取到button这个dom
console.log(couterRef.current);
}, [count]);
return (
<>
//与ref类似,绑定到button标签上
<button ref={
couterRef} onClick={
() => {
setCount(count + 1)}}>Count: {
count}, double: {
doubleCount}</button>
</>
);
}
第二种,跨组件获取子组件的方法。
在以往的ref中,可以将ref绑定到某个子组件标签上,用以获取整个子组件的方法和参数,在react 的useref也有类似的功能。
父组件代码
import React, {
useRef } from 'react';
import StudentStatusForm from './components/student-status-info-emdit//student-status-info-emdit';
const StudentBase: React.FC = (props) => {
const onClickConfirmStudentStatusInfo = () => {
//获取StudentStatusForm 子组件onFinish方法
userInfoStatus.current
.onFinish()
.validateFields()
.then(() => {
setStudentInfoStatus(0);
});
};
const userInfoStatus = useRef();
return (
<>
//当点击Button的时候获取StudentStatusForm 子组件的onFinish方法
<Button onClick={
onClickConfirmStudentStatusInfo }>获取onFinish方法</Button>
<StudentStatusForm ref={
userInfoStatus} initialValues={
studentDetailsData} />
</>
)
}
export default StudentBase;
子组件代码
import React, {
useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import {
Form} from 'antd';
//子组件不再使用react的React方式来创建,直接通过函数的方式创建,函数子组件接收两个参数,第一个参数是父组件传过来的其它参数,第二个参数是ref
const StudentStatusForm = (props: StudentStatusFormType, ref: any) => {
const {
initialValues } = props;
const [form] = Form.useForm();
const onFinish = () => {
return form;
};
useEffect(() => {
const newInitialValues = {
...initialValues}
newInitialValues.admissionDate = moment(initialValues.admissionDate);
newInitialValues.birthday = moment(initialValues.birthday);
form.setFieldsValue(newInitialValues);
}, [initialValues]);
//react规定,必须使用useImperativeHandle方法,来保存并抛出想要传递给父组件的方法或者数据,第一个参数是ref,第二个参数是函数,返回想要抛出的对象集合
useImperativeHandle(ref, () => ({
onFinish,
}));
return (
<div className="student-status-info-emdit">
<Form {
...formItemLayout} form={
form}>
</Form>
</div>
);
};
//必须通过forwardRef方法抛出函数组件
export default forwardRef(StudentStatusForm);
不常用却好用的useref骚操作
在react中,无论是使用usestate来保存数据,如果这数据被修改,将会引起页面的重新渲染。
可有时候,我们想要保存的数据不大,但当数据改变的时候不想页面重新渲染,这份数据在页面多次重新渲染后仍然能保持不变。
要做到以上条件使用什么方法呢?
1 reducer 感觉多少还是有些麻烦,
2 保存到浏览器locationstoreage,取的时候也麻烦,不安全。
3 保存到服务器,可能你会被骂死,这么一点小数据还要麻烦后端。
4 保存到useref里面去。
import React, {
useState, useEffect, useMemo, useRef } from 'react';
export default function App(props){
const [count, setCount] = useState(0);
const doubleCount = useMemo(() => {
return 2 * count;
}, [count]);
// 创建useRef
const timerID = useRef();
useEffect(() => {
// 不从useRef取值,而是赋值给它,用来保存定时器格外酸爽
timerID.current = setInterval(()=>{
setCount(count => count + 1);
}, 1000);
}, []);
useEffect(()=>{
if(count > 10){
// 当你需要使用的时候,依然存在,停掉定时器,
clearInterval(timerID.current);
}
});
return (
<>
//绑定ref
<button ref={
couterRef} onClick={
() => {
setCount(count + 1)}}>Count: {
count}, double: {
doubleCount}</button>
</>
);
}
上面代码不是我写的,来自一位大神的博客,偶然发现,与大家分享一下。
https://blog.csdn.net/hjc256/article/details/102587037