我正在尝试测量我的卡片在它的父宽度上的移动。单击时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;
}
1条答案
按热度按时间46qrfjad1#
答案在于我将App.tsx中的引用和Client.tsx中的引用命名为相同的名称。这导致react每次返回两个可能的引用,这使得无法更新x值。我还必须更新useEffect依赖项。