onClick事件。更换React组件后detail未重置

问题描述 投票:0回答:1

onClick事件.detail包含点击次数:双击有

event.detail = 2

当点击的React组件被替换时,event.detail不会重置。我怀疑这是因为 React 对此进行了优化并在页面中保留了相同的 div,因此浏览器没有重置 event.detail 计数器。

如何在组件更改时强制重置此 event.detail 计数器?我希望能够在导航时多次双击列表中的项目。

问题重现:https://codesandbox.io/p/sandbox/react-on-click-event-detail-6ndl5v?file=%2Fsrc%2FApp.tsx%3A44%2C12

App.tsx:

const ListItem: React.FC<{
  content: string;
  onClick: (event: React.MouseEvent<HTMLDivElement>) => void;
}> = ({ content, onClick }) => {
  return (
    <div
      onClick={onClick}
      style={{ background: "rgba(0,0,0,0.5)", userSelect: "none" }}
    >
      {content}
    </div>
  );
};

const ListRenderer: React.FC = () => {
  // n tracks the number of double clicks
  const [n, setN] = useState(0);

  // items simulates an updating list of items when double-clicking
  const items = useMemo(
    () => Array.from({ length: 10 }, (_, i) => `${n}: item ${i}`),
    [n]
  );

  const handleClick = useCallback((event: React.MouseEvent<HTMLDivElement>) => {
    console.log(`Click: event.detail: ${event.detail}`);
    if (event.detail === 2) {
      // Double-clicked an item.
      setN((prev) => prev + 1);
    }
  }, []);

  return (
    <>
      <div>
        {items.map((item, index) => (
          <ListItem
            key={`items-${n}-${index}`}
            content={item}
            onClick={handleClick}
          />
        ))}
      </div>
    </>
  );
};

javascript reactjs dom onclick dom-events
1个回答
0
投票

经过一些实验,我编写了这个 React Hook 来检测重新安装组件后 event.detail 何时未正确重置,并相应地更正点击计数:

import { useCallback, useRef } from 'react'

// MouseEvent and other events satisfy this.
interface DetailCountEvent {
  // detail is the number of times the event occurred.
  detail: number
}

// useDetailCountHandler builds an event handler which correctly resets the
// event.detail counter when the component is re-mounted.
//
// The onClick event.detail contains the number of clicks: double-click has
// event.detail = 2. When the clicked React component is replaced, the
// event.detail does not reset.
//
// Question: https://stackoverflow.com/q/77719428/431369
// Issue: https://codesandbox.io/p/sandbox/react-on-click-event-detail-6ndl5v?file=%2Fsrc%2FApp.tsx%3A8%2C23
// Fix: https://codesandbox.io/p/sandbox/react-on-click-event-detail-possible-fix-4zwk7d?file=%2Fsrc%2FApp.tsx%3A59%2C1
export function useDetailCountHandler<E extends DetailCountEvent>(
  cb: (e: E, count: number) => void,
) {
  const stateRef = useRef({ prev: 0, sub: 0 })
  return useCallback(
    (e: E) => {
      const state = stateRef.current
      let count = e.detail
      if (state.sub >= count) {
        state.sub = 0
      }
      if (state.prev < count - 1) {
        state.sub = count - state.prev - 1
      }
      count -= state.sub
      state.prev = count
      cb(e, count)
    },
    [stateRef, cb],
  )
}

用途:

const handleClick: MouseEventHandler<HTMLDivElement> = 
    useDetailCountHandler(
        useCallback(
            (e, count) => {
                console.log('onClick', e.detail, count);
                if (count === 2) {
                    // double click
                }
            },
            [],
        ),
    );

return <div onClick={handleClick} />;

使用

key
强制React重新创建div,不幸的是不会重置onClick中的event.detail。

上面的钩子有点像黑客,但工作可靠。如果其他人有一种在组件更改时重置 event.detail 的不那么麻烦的方法,我很想知道。

© www.soinside.com 2019 - 2024. All rights reserved.