React Hooks UseRef的用法

开发环境时Taro+React Native+TypeScript

TypeScript 复制代码
export interface TimerRef{
  timeShow: ()=>{};
  getCurrentTime: () => number;
}

// 修改这里:添加 props 参数,即使不使用也要保留位置
const Timer = forwardRef<TimerRef, {}>((props, ref) => {
  const [count, setCount] = useState(0);
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const memoryName = 'Time Pace'

  // 暴露方法给父组件
  useImperativeHandle(ref, ()=>({
    timeShow: ()=>{
      console.log("定时器的当前时间: current time = ", count)
      console.log("memoryName = ", memoryName)
    },
    getCurrentTime: ()=>{
      return count
    }
    
  }))

  const startTimer = () => {
    // 如果已经有定时器在运行,先清除
    if (timerRef.current !== null) {
      clearInterval(timerRef.current);
    }
    timerRef.current = setInterval(() => {
      setCount(prev => prev + 1);
    }, 1000);
  };

  const stopTimer = () => {
    if (timerRef.current !== null) {
      clearInterval(timerRef.current);
      timerRef.current = null; // 清除后重置为 null
    }
  };

  useEffect(() => {
    return () => {
      if (timerRef.current !== null) {
        clearInterval(timerRef.current);
      }
    };
  }, []);

  return (
    <div>
      <p>计数: {count}</p>
      <button className='btn' style={{marginRight: 20}} onClick={startTimer}>开始</button>
      <button className='btn' onClick={stopTimer}>停止</button>
    </div>
  );
})
TypeScript 复制代码
import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react'
import { View, Text, Button } from '@tarojs/components'
import './index.scss'

interface IProps{
  color: string;
  size: string;
  originalPrice?: string;
  description?: string;
  likeStar?: string;
  price: number;
}

const DressPaper = (props:IProps) => {

  const [price, setPrice] = useState(props.price)
  const [likeStar, setLikeStar] = useState(props.likeStar || 'star, ')
  const priceRef = useRef<HTMLSpanElement>(null)
  const preStarsNumRef = useRef(0)
  const timeRef = useRef<TimerRef>(null)
  

  // 改变价格
  const changeDressPrice = ()=>{
    setPrice(prePrice =>{
      return ++prePrice 
    });

    // 使用useRef动态改变元素的样式
    if(priceRef.current){
      // const element = priceRef.current as unknown as HTMLElement;
      priceRef.current.style.color = 'blue'
    }
  }

  // 使用ref存储上一次的值
  // 增加like Star并记录上一次增加后的次数
  const addLikeStar = ()=>{
    setLikeStar(preLikeStar => {
      return preLikeStar + 'star, '
    })
    // useRef修饰的值跨越整个生命周期都不会改变,但当值改变时也可以更新在页面中
    preStarsNumRef.current++
  }

  //子组件的事件处理
  const handleSubShow = ()=>{
    console.log("通过ref在子组件中获取的当前时间 current time = ", timeRef.current?.getCurrentTime())
    timeRef.current?.timeShow()
  }

  return (<View>
    <View className='container'>
      <Text ref={priceRef} className='txt'>Price: {'$' + price}</Text>
      <Text className='txt'>{likeStar}</Text>
      <Text className='txt'>上一次增加的star个数为:{preStarsNumRef.current}</Text>
    </View>
    <View>
      <Button className='btn' onClick={changeDressPrice}>change price</Button>
      <Button className='btn' onClick={addLikeStar}>add like star</Button>
    </View>
    <View style={{backgroundColor: '#cc9999'}}>
      <Text className='txt'>
        使用useRef做父子组件间的通信,存储定时器, 组件销毁时清除定时器
      </Text>
      <Timer ref={timeRef}></Timer>
      <Button className='btn' onClick={handleSubShow}>
        父组件调用子组件方法,修改子组件的属性
      </Button>
    </View>
  </View>
  );
}

export default DressPaper;
TypeScript 复制代码
import UseRefComponent from "../Hooks/UseRef";
<UseRefComponent color='blue' size='m' price={20}></UseRefComponent>

下面的是样式scss文件

TypeScript 复制代码
.container {
  display: flex;
  flex-direction: column;
  padding: 20px;
  background-color: #ADD8E6;
  margin-bottom: 40px;
}

.txt {
  height: 44px;
  padding: 15px 100px;
  margin-bottom: 7px;
  background-color: #FFE4E1;
  font-size: 26px;
}

.btn {
  height: 64px;
  // padding: 15px 100px 15px 100px;
  margin-bottom: 7px;
  background-color: #D8BFD8;
  font-size: 28px;
}

.buttonContainer {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  margin-bottom: 20px;
}

.input {
  background-color: white;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}
相关推荐
2401_83150173几秒前
Python学习之Day05学习(定制数据对象,面向对象)
前端·python·学习
GISer_Jing11 分钟前
得物前端二面潜在问题详解
前端·javascript·面试
飞天巨兽1 小时前
HTTP基础教程详解
前端·网络·网络协议·http
FIN66681 小时前
昂瑞微IPO前瞻:技术破局高端射频模组,国产替代第二波浪潮下的硬科技突围
前端·科技·搜索引擎·产品运营·创业创新·制造·射频工程
玉树临风江流儿1 小时前
Cmake使用CPack实现打包
java·服务器·前端
xier1234563 小时前
一个全新的react表格组件方案
前端
未来之窗软件服务3 小时前
从东方仙盟筑基期看 JavaScript 动态生成图片技术-东方仙盟
开发语言·javascript·仙盟创梦ide·东方仙盟·图片技术
不叫猫先生4 小时前
中秋连连看小游戏开发完整教程
javascript·css·小游戏·连连看
IT_陈寒4 小时前
5种JavaScript性能优化技巧:从V8引擎原理到实战提速200%
前端·人工智能·后端
蒋星熠4 小时前
Maven项目管理与构建自动化完全指南
java·前端·python·自动化·maven