【react】使用useEffect操作dom

news2024/12/29 11:49:40

简言

在学习react时,需要了一个需要在useEffect里操作dom的用法。
一般不推荐这么干,如果是函数组件在一渲染已挂载后立即需要操作dom绑定事件等可以参考下面解决方法。

描述

官网交错运动示例

在这里插入图片描述

这个示例中,usePointerPosition() Hook 追踪当前指针位置。尝试移动光标或你的手指到预览区域上方,可以看到有一个红点随着你移动。它的位置被保存在变量 pos1 中。

事实上,有 5(!)个正在被渲染的不同红点。你看不见是因为他们现在都显示在同一位置。这就是你需要修复的问题。你想要实现的是一个“交错”运动:每个圆点应该“跟随”它前一个点的路径。例如如果你快速移动光标,第一个点应该立刻跟着它,第二个应该在小小的延时后跟上第一个点,第三个点应该跟着第二个点等等。

你需要实现自定义 Hook useDelayedValue。它当前的实现返回的是提供给它的 value。而你想从 delay 毫秒之前返回 value。你可能需要一些 state 和一个 Effect 来完成这个任务。

实现 useDelayedValue 后,你应该看见这些点一个接一个运动。

解决答案:
app.jsx

import { useState, useEffect } from 'react';
import { usePointerPosition } from './usePointerPosition.js';

function useDelayedValue(value, delay) {
  const [delayedValue, setDelayedValue] = useState(value);

  useEffect(() => {
    setTimeout(() => {
      setDelayedValue(value);
    }, delay);
  }, [value, delay]);

  return delayedValue;
}

export default function Canvas() {
  const pos1 = usePointerPosition();
  const pos2 = useDelayedValue(pos1, 100);
  const pos3 = useDelayedValue(pos2, 200);
  const pos4 = useDelayedValue(pos3, 100);
  const pos5 = useDelayedValue(pos3, 50);
  return (
    <>
      <Dot position={pos1} opacity={1} />
      <Dot position={pos2} opacity={0.8} />
      <Dot position={pos3} opacity={0.6} />
      <Dot position={pos4} opacity={0.4} />
      <Dot position={pos5} opacity={0.2} />
    </>
  );
}

function Dot({ position, opacity }) {
  return (
    <div style={{
      position: 'absolute',
      backgroundColor: 'pink',
      borderRadius: '50%',
      opacity,
      transform: `translate(${position.x}px, ${position.y}px)`,
      pointerEvents: 'none',
      left: -20,
      top: -20,
      width: 40,
      height: 40,
    }} />
  );
}

usePointerPosition.js

import { useState, useEffect } from 'react';

export function usePointerPosition() {
  const [position, setPosition] = useState({ x: 0, y: 0 });
  useEffect(() => {
    function handleMove(e) {
      setPosition({ x: e.clientX, y: e.clientY });
    }
    window.addEventListener('pointermove', handleMove);
    return () => window.removeEventListener('pointermove', handleMove);
  }, []);
  return position;
}

这个是 react的一个hook函数,作用就是根据当前计算更新当前鼠标的位置。
如果是一个新的页面且只有这个示例是正常的。
不过示例前面还用元素就会出现偏差。
解决方案是在外面包括一个相对定位的盒子,然后在这个相对定位盒子里监听鼠标移动事件,更新小球偏离位置。
所以,这需要react挂载后就立即在这个相对定位盒子里监听鼠标移动事件
在这里插入图片描述

解决方法

方法1 usePointerPosition.js hook传递dom参数。

参数box:这个代表使用useRef绑定的盒子dom对象
hook作用:在挂载后立即给box.current绑定鼠标移动事件,事件会更新position对像的值,最后返回。

function usePointerPosition(box){
  const [position,setPosition] = useState({x:0,y:0})

  useEffect(()=>{
  	  let dom = box.current
   
 
	  if(dom)
	  dom.addEventListener("mousemove",handleMove)
	  function handleMove(e){
	    // console.log(e.clientX,e.clientY)
	  setPosition({x:e.offsetX,y:e.offsetY});
	} 

  return ()=>{
      if(dom)
      dom.removeEventListener("mousemove",handleMove)
    }
  },[box])
  return position
}

改造好后,可以和以前一样使用,参数传递useRef的dom对象就行。
在这里插入图片描述

方法2. usePointerPosition.js hook传递回调函数参数。

使用时,直接在回调函数内,给dom盒子绑定鼠标移动事件

function usePointerPosition2(callback){
  const [position,setPosition] = useState({x:0,y:0})

  useEffect(()=>{
   // 回调函数传递移动事件要使用的函数,返回dom对象,
  let dom = callback(handleMove)
  
  function handleMove(e){
  setPosition({x:e.offsetX,y:e.offsetY});
} 
    return ()=>{
      if(dom)
      dom.removeEventListener("mousemove",handleMove)
    }
    //  报错很正常,因为使用callback依赖项,却没在下面绑定,下一句是规避掉代码检查
  // eslint-disable-next-line react-hooks/exhaustive-deps
  },[])
  return position
}

使用:

 let pos1 = usePointerPosition(
(handleMove)=>{
  console.log(11);
      box.current.addEventListener("mousemove",handleMove)
    return box.current
     }
);

方法3 使用useCallBack hook代替规避代码检查

官方是极其不推荐使用 注释 // eslint-disable-next-line react-hooks/exhaustive-deps规避代码检查的。
我们又确定callback的内容只变化一次,如果不使用注释,而将callback函数作为依赖项的话,将会执行多次callback函数,每次渲染都会执行,因为函数本身在渲染时在变。
这时 我们可以使用useCallback将callback包裹一下,缓存住,这样再渲染就是原来的函数。
useCallback 是一个允许你在多次渲染中缓存函数的 React Hook。
在这里插入图片描述
改造 usePointerPosition.

function usePointerPosition3(callback){
  const [position,setPosition] = useState({x:0,y:0})

  useEffect(()=>{
   // 回调函数返回dom对象
  let dom = callback(handleMove)
  
  function handleMove(e){
  setPosition({x:e.offsetX,y:e.offsetY});
} 
    return ()=>{
      if(dom)
      dom.removeEventListener("mousemove",handleMove)
    }
    //  报错很正常,因为使用callback依赖项,却没在下面绑定,下一句是规避掉代码检查
  },[callback])
  return position
}```

使用

```javascript
import {useEffect,useState} from 'react'
import { useRef } from 'react';
import { useCallback } from "react";


const callback = useCallback(
    (handleMove)=>{
      console.log(11);
      box.current.addEventListener("mousemove",handleMove)
      return box.current
    }
  ,[box])
  let pos1 = usePointerPosition(callback);

这样callback就不会多次改变导致useEffect重复执行了。

结语。

在useEffect里操作dom是比较危险的。如果有其他更好的替代方案,请使用其他的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1033119.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【前段基础入门之】=>初识 HTML

文章目录 前言HTML的详情简介HTML 发展史HTML 入门1. HTML 标签元素2. HTML标签属性3. HTML的标准结构 总结 前言 在整个前端开发中&#xff0c;必须掌握的技术栈为&#xff1a; HTML &#xff0c;CSS&#xff0c;JavaScript&#xff0c;它们三者&#xff0c;共同组成了前端开发…

华为云云耀云服务器L实例评测|认识redis未授权访问漏洞 漏洞的部分复现 设置连接密码 redis其他命令学习

前言 最近华为云云耀云服务器L实例上新&#xff0c;也搞了一台来玩&#xff0c;期间遇到过MySQL数据库被攻击的情况&#xff0c;数据丢失&#xff0c;还好我有几份备份&#xff0c;没有造成太大的损失。昨天收到华为云的邮箱提醒&#xff0c;我的redis数据库没有设置密码&…

MySQL高级语句 Part2(视图表 +存储过程+条件语句+循环语句)

这里写目录标题 一、视图表 create view1.1 视图表概述1.2 视图表能否修改&#xff1f;&#xff08;面试题&#xff09;1.3 基本语法1.3.1 创建1.3.2 查看1.3.3 删除 1.4 通过视图表求无交集值 二、case语句三、空值(null) 和 无值( ) 的区别四、正则表达式4.1 基本语法和匹配模…

pcl--第十二节 2D和3D融合和手眼标定

2D&3D融合 概述 截止目前为止&#xff0c;我们学习了机器人学&#xff0c;学习了2D和3D视觉算法。我们也学习了2D相机(图像数据的来源)和3D相机(点云数据的来源)工作原理。 实际上&#xff0c;我们最终要做的&#xff0c;是一个手眼机器人系统。在这个系统里&#xff0c…

数据仓库整理

数仓 olap vs oltp OLTP主要用于支持日常的业务操作&#xff0c;如银行交易、电子商务等&#xff0c;强调数据的准确性、实时性和并发性。OLAP主要用于支持复杂的数据分析&#xff0c;如数据仓库、决策支持等&#xff0c;强调数据的维度、聚合和可视化。 将OLTP数据库的数据…

接入国家能源平台MQTT应用案例

一、项目介绍 随着国家对节能环保措施的力度不断加大&#xff0c;基于物联网技术搭建的国家能源平台在国家相关部门的建设下逐渐成熟。致力于利用实际能耗数据建立能效仿真模型&#xff0c;通过实时寻优运算&#xff0c;获得当前的最优化运行策略&#xff0c;并将控制指令下发…

从Langchain到ReAct,在大模型时代下全新的应用开发核心

简介&#xff1a; 什么是ReAct框架关于什么是langchain&#xff0c;可以参考&#xff1a;https://ata.alibaba-inc.com/articles/266839?spmata.23639420.0.0.1dea7536uD7yhh在使用langchain的过程中&#xff0c;大模型给人留下最深刻的印象无疑是Agent功能。大模型会自己分析…

@Cacheable 注解(指定缓存位置)

一、Cacheable的作用 1、缓存使用步骤&#xff1a;Cacheable这个注解&#xff0c;用它就是为了使用缓存的。所以我们可以先说一下缓存的使用步骤&#xff1a; 1、开启基于注解的缓存&#xff0c;使用 EnableCaching 标识在 SpringBoot 的主启动类上。 2、标注缓存注解即可 使用…

【Less-CSS】初识Less,使编写 CSS 变得简洁

初识Less&#xff0c;使编写 CSS 变得简洁 1.Less简述2.LESS 原理及使用方式3.示例4.less语法5.Easy Less插件 作为一门标记性语言&#xff0c;CSS 的语法相对简单&#xff0c;对使用者的要求较低&#xff0c;但同时也带来一些问题&#xff1a;CSS 需要书写大量看似没有逻辑的代…

【初阶数据结构】二叉树链式结构的实现和遍历

个人主页 代码仓库 C语言专栏 初阶数据结构专栏 Linux专栏 目录 前言 二叉树链式结构的实现 二叉树的遍历 前序、中序和后序遍历 前序遍历 中序遍历 后序遍历 求结点个数 求总的结点个数 创建变量求结点 创建静态修饰变量 拆分左右子树加根 求叶子节点的个…

LeetCode【65. 有效数字】

没有完美的傀儡,没有完美的人类,却有绝美的离逝。 有效数字&#xff08;按顺序&#xff09;可以分成以下几个部分&#xff1a; 一个 小数 或者 整数&#xff08;可选&#xff09;一个 e 或 E &#xff0c;后面跟着一个 整数 小数&#xff08;按顺序&#xff09;可以分成以下几…

2023华为杯研究生数学建模竞赛CDEF题思路+模型代码

全程更新华为杯研赛CDEF题思路模型及代码&#xff0c;大家查看文末名片获取 华为杯C题思路分析 问题一 在每个评审阶段&#xff0c;作品通常都是随机分发的&#xff0c;每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比性&#xff0c;不同专家评审的作…

【Java毕设项目】基于SpringBoot+Vue校园便利平台的设计与实现

博主主页&#xff1a;一季春秋博主简介&#xff1a;专注Java技术领域和毕业设计项目实战、Java、微信小程序、安卓等技术开发&#xff0c;远程调试部署、代码讲解、文档指导、ppt制作等技术指导。主要内容&#xff1a;毕业设计(Java项目、小程序等)、简历模板、学习资料、面试题…

3.6+铁死亡+WGCNA+机器学习

今天给同学们分享一篇3.6铁死亡WGCNA机器学习的生信文章“Identification of ferroptosis related biomarkers and immune infiltration in Parkinsons disease by integrated bioinformatic analysis”&#xff0c;这篇文章于2023年3月14日发表在BMC Med Genomics期刊上&#…

【笔记】ubuntu 20.04 + mongodb 4.4.14定时增量备份脚本

环境 ubuntu 20.04mongodb 4.4.14还没实际使用&#xff08;20230922&#xff09;后续到10月底如果有问题会修改 原理 只会在有新增数据时生成新的备份日期目录备份恢复时&#xff0c;如果恢复的数据库未删除&#xff0c;则会覆盖数据 准备 准备一个文件夹&#xff0c;用于…

2023华为杯数学建模竞赛E题

一、前言 颅内出血&#xff08;ICH&#xff09;是由多种原因引起的颅腔内出血性疾病&#xff0c;既包括自发性出血&#xff0c;又包括创伤导致的继发性出血&#xff0c;诊断与治疗涉及神经外科、神经内科、重症医学科、康复科等多个学科&#xff0c;是临床医师面临的重要挑战。…

Springboot2 Pandas Pyecharts 量子科技专利课程设计大作业

数据集介绍 1.背景 根据《中国科学&#xff1a;信息科学》期刊上的一篇文章&#xff0c;量子通信包括多种协议与应用类型&#xff1a; 基于量子隐形传态与量子存储中继等技术&#xff0c;可实现量子态信息传输&#xff0c;进而构建量子信息网络&#xff0c;已成为当前科研热点&…

成为威胁:网络安全中的动手威胁模拟案例

不断变化的网络威胁形势要求组织为其网络安全团队配备必要的技能来检测、响应和防御恶意攻击。然而&#xff0c;在研究中发现并继续探索的最令人惊讶的事情是&#xff0c;欺骗当前的网络安全防御是多么容易。 防病毒程序建立在庞大的签名数据库之上&#xff0c;只需更改程序内…

聊聊自动化测试路上会遇到的挑战~

一、测试范围 无论是功能测试&#xff0c;还是自动化或者性能测试&#xff0c;第一步要做的&#xff0c;是明确测试范围和需求指标。对于自动化测试来说&#xff0c;特别是UI自动化&#xff0c;并不是所有的功能点都适合做UI自动化。 根据具体的业务情况和项目稳定程度&#…

Unity之Hololens2开发 如何接入的MRTK OpenXR Plugin

一.前言 什么是Hololens? Hololens是由微软开发的一款混合现实头戴式设备,它将虚拟内容与现实世界相结合,为用户提供了沉浸式的AR体验。Hololens通过内置的传感器和摄像头,能够感知用户的环境,并在用户的视野中显示虚拟对象。这使得用户可以与虚拟内容进行互动,将数字信…