reactjs 如何在React中测量旋转木马的x轴运动?

nr7wwzry  于 2023-05-28  发布在  React
关注(0)|答案(1)|浏览(131)

我正在尝试测量我的卡片在它的父宽度上的移动。单击时X轴不更新。下面是代码片段。主要目标是在客户端组件在屏幕上不可见时执行某些操作。我一直在尝试在useRect钩子中使用getBoundingClientRect。我最好的猜测是钩子依赖关系不正确,或者引用没有成功传递。对不起,我不能再减少代码了。
App.tsx

import { useState, useEffect } from 'preact/hooks'
import { createRef } from 'preact/compat';
import './app.css'
import Client from './components/Client';
import { useRect } from './hooks/useRect';

export function App() {
  const [translate, setTranslate] = useState<number>(0)

  function moveCard(prev: number) {
    setTranslate(prev += 20)
  }
  const contentRef = createRef<HTMLDivElement>();
  const carouselRect = useRect(contentRef)
  const {right: carouselEndPoint} = carouselRect;

  return (
    <>
    <button class='bg-slate-300 absolute top-2 left-2 ' onClick={() => {
      moveCard(translate)
    }}> Click to call function</button>
      <div ref={contentRef} className="grid grid-cols-4 bg-slate-200 gap-3 grid-flow-col w-4/5 mx-auto overflow-clip">
        <Client carouselEndPoint={carouselEndPoint} translate={`${translate}%`} setTranslate={setTranslate} name="1"/>
      </div>
    </>
  )
}

Client.tsx

import logo from '../assets/preact.svg'
import { useEffect } from 'preact/hooks'
import { useRect } from '../hooks/useRect'
import { StateUpdater, createRef } from 'preact/compat'

export interface ClientProps {
  name: string
  translate: string
  setTranslate: StateUpdater<number>
  carouselEndPoint: number
  width?: string | number
  // contentRef?: RefObject<HTMLDivElement>
}

function Client({name, translate, setTranslate, carouselEndPoint}: ClientProps) {

  const contentRef = createRef<HTMLDivElement>();
  const val = useRect(contentRef)
  const {left: clientX} = val;

  useEffect(() => {
    console.log(val);
    if(clientX >= carouselEndPoint) {
      console.log('hidden');
    }
  }, [translate])
  
  return (
      <div className="flex flex-col basis-auto bg-slate-300 items-center drop-shadow-md rounded-md w-full place-content-center transition-transform ease-linear duration-1000 overflow-clip" style={`transform: translateX(${translate})`} 
      ref={contentRef}>
        {/* client card */}
        <img className='h-full w-full' src={logo}/>
        <h3 className="text-5xl">{name}</h3>
      </div>
  )
}

export default Client;

useRect.tsx

// source: https://gist.github.com/morajabi/523d7a642d8c0a2f71fcfa0d8b3d2846
import { RefObject } from 'preact'
import { useLayoutEffect, useCallback, useState } from "preact/hooks";

type RectResult = {
  bottom: number;
  height: number;
  left: number;
  right: number;
  top: number;
  width: number;
};

function getRect<T extends HTMLElement>(element?: T): RectResult {
  let rect: RectResult = {
    bottom: 0,
    height: 0,
    left: 0,
    right: 0,
    top: 0,
    width: 0,
  };
  if (element) rect = element.getBoundingClientRect();
  return rect;
}

export function useRect<T extends HTMLElement>(
  ref: RefObject<T>
): RectResult {
  const [rect, setRect] = useState<RectResult>(
    ref && ref.current ? getRect(ref.current) : getRect()
  );

  const handleResize = useCallback(() => {
    if (!ref.current) return;
    setRect(getRect(ref.current)); // Update client rect
  }, [ref]);

  useLayoutEffect(() => {
    const element = ref.current;
    if (!element) return;

    handleResize();

    if (typeof ResizeObserver === "function") {
      
      const resizeObserver = new ResizeObserver(() => handleResize());
      resizeObserver.observe(element);
      return () => {
        if (!resizeObserver) return;
        resizeObserver.disconnect();
        // resizeObserver = null;
      };
    } else {
      window.addEventListener("resize", handleResize); // Browser support, remove freely
      return () => window.removeEventListener("resize", handleResize);
    }
  }, [ref.current]);

  return rect;
}
46qrfjad

46qrfjad1#

答案在于我将App.tsx中的引用和Client.tsx中的引用命名为相同的名称。这导致react每次返回两个可能的引用,这使得无法更新x值。我还必须更新useEffect依赖项。

相关问题