【问题标题】:Using array of Refs intead of single Ref使用 Refs 数组而不是单个 Ref
【发布时间】:2022-12-09 18:10:01
【问题描述】:

我在地图循环中使用 ref。 我需要一组参考 问题是 ref 只针对列表中生成的最后一个元素 这是我准备的例子, 我需要通过 ref 列表在地图循环内的所有生成元素上运行自定义挂钩

我在找办法无需引入另一个组件

import React, { useRef, useState, useEffect, useCallback } from "react";

/// throttle.ts
export const throttle = (f) => {
  let token = null,
    lastArgs = null;
  const invoke = () => {
    f(...lastArgs);
    token = null;
  };
  const result = (...args) => {
    lastArgs = args;
    if (!token) {
      token = requestAnimationFrame(invoke);
    }
  };
  result.cancel = () => token && cancelAnimationFrame(token);
  return result;
};

const id = (x) => x;
const useDraggable = ({ onDrag = id } = {}) => {
  const [pressed, setPressed] = useState(false);

  const position = useRef({ x: 0, y: 0 });
  const ref = useRef();

  const unsubscribe = useRef();
  const legacyRef = useCallback((elem) => {
    ref.current = elem;
    if (unsubscribe.current) {
      unsubscribe.current();
    }
    if (!elem) {
      return;
    }
    const handleMouseDown = (e) => {
      e.target.style.userSelect = "none";
      setPressed(true);
    };
    elem.addEventListener("mousedown", handleMouseDown);
    unsubscribe.current = () => {
      elem.removeEventListener("mousedown", handleMouseDown);
    };
  }, []);

  useEffect(() => {
    if (!pressed) {
      return;
    }

    const handleMouseMove = throttle((event) => {
      if (!ref.current || !position.current) {
        return;
      }
      const pos = position.current;

      const elem = ref.current;
      position.current = onDrag({
        x: pos.x + event.movementX,
        y: pos.y + event.movementY
      });
      elem.style.transform = `translate(${pos.x}px, ${pos.y}px)`;
    });
    const handleMouseUp = (e) => {
      e.target.style.userSelect = "auto";
      setPressed(false);
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);
    return () => {
      handleMouseMove.cancel();
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
    };
  }, [pressed, onDrag]);

  return [legacyRef, pressed];
};

/// example.ts
const quickAndDirtyStyle = {
  width: "200px",
  height: "200px",
  background: "#FF9900",
  color: "#FFFFFF",
  display: "flex",
  justifyContent: "center",
  alignItems: "center"
};

const DraggableComponent = () => {
  const handleDrag = useCallback(
    ({ x, y }) => ({
      x: Math.max(0, x),
      y: Math.max(0, y)
    }),
    []
  );

  const [ref, pressed] = useDraggable({
    onDrag: handleDrag
  });

  return (
    <>
      {[1, 2, 3].map((el, i) => (
        <div key={"element" + i} ref={ref} style={quickAndDirtyStyle}>
          <p>{pressed ? "Dragging..." : "Press to drag"}</p>
        </div>
      ))}
    </>
  );
};

export default function App() {
  return (
    <div className="App">
      <DraggableComponent />
    </div>
  );
}

codesandbox 的链接在这里 https://codesandbox.io/s/determined-wave-pfklec?file=/src/App.js

【问题讨论】:

    标签: javascript reactjs react-hooks draggable use-ref


    【解决方案1】:

    在 useDraggable 函数中,创建一个 refs 数组:

      const refs = useRef([]);
      const unsubscribe = useRef();
      const legacyRef = useCallback((elem, index) => {
        refs.current[index] = elem;
        if (unsubscribe.current) {
          unsubscribe.current();
        }
        if (!elem) {
          return;
        }
    

    在 handleMouseMove 使用这个数组:

    if (!refs.current || !position.current) {
            return;
          }
          const pos = position.current;
    
          const elem = refs.current[index];
          position.current = onDrag({
    [...]
    

    这个想法是使用数组索引将 ref 分配给每个元素。 j希望有帮助

    【讨论】:

      【解决方案2】:

      您可以像这样使用 ref 。

       let ref = [];
      

      并像这样使用它。

      ref={(element) =&gt; (flatlistRef[index] = element)}

      你也可以像这样使用地图功能。

      ref.map(async (item, index) =&gt; {})

      【讨论】:

      • 你能在代码中演示吗?我知道这个 !但问题出在行 const [ref, pressed] = useDraggable({ onDrag: handleDrag });你如何在这里使用 ref 数组??
      • 我已经在我的应用程序中演示了这一点。但正如我所说,我不会那样使用它。
      • 我不明白在说什么,但还是谢谢你的回答
      猜你喜欢
      • 1970-01-01
      • 2023-02-03
      • 2011-03-04
      • 2021-08-20
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      • 2018-05-29
      相关资源
      最近更新 更多