【问题标题】:How can I assign a new ref to every iteration inside a map function?如何为 map 函数内的每次迭代分配一个新的 ref?
【发布时间】:2020-04-04 00:35:53
【问题描述】:

我不知道怎么问这个问题,因为我仍然无法准确地描述问题。

我创建了一个 useHover 函数。下面,您将看到我正在映射数据并渲染一堆照片。但是,useHover 仅适用于第一次迭代。

我怀疑这是因为我的裁判。这是如何运作的?我应该在每次迭代中创建一个新的参考 - 还是那个错误的想法..?

我该怎么做?

这是我的 useHover 函数。

const useHover = () => {
  const ref = useRef();
  const [hovered, setHovered] = useState(false);

  const enter = () => setHovered(true);
  const leave = () => setHovered(false);

  useEffect(() => {
    ref.current.addEventListener("mouseenter", enter);
    ref.current.addEventListener("mouseleave", leave);

    return () => {
      ref.current.removeEventListener("mouseenter", enter);
      ref.current.removeEventListener("mouseleave", leave);
    };
  }, [ref]);

  return [ref, hovered];
};

这是我的地图功能。如您所见,我已将 ref 分配给图像。

问题:悬停时只有一张图像有效。

const [ref, hovered] = useHover();

  return (
    <Wrapper>
      <Styles className="row">
        <Div className="col-xs-4">
          {data.map(item => (
            <div className="row imageSpace">
              {hovered && <h1>{item.fields.name}</h1>}
              <img
                ref={ref}
                className="image"
                key={item.sys.id}
                alt="fall"
                src={item.fields.image.file.url}
              />
            </div>
          ))}
        </Div>

【问题讨论】:

  • 好像会的。不知道如何实现这一点。
  • 您只需要在单独组件中的迭代器中使用useHover。 @T.J。克劳德回答会解决你的问题
  • @Dupocas - 同意,这是一个副本。可悲的是,还没有赞成或接受的答案。 :-)
  • 指向我自己的答案似乎有点自私,对吧?哈哈哈,你的似乎更具体。我正在删除评论并支持你的评论

标签: javascript reactjs react-hooks ref


【解决方案1】:

如果可能的话,我会使用 CSS 来处理这个问题,而不是在我的 JavaScript 代码中处理悬停。

如果在 JavaScript 代码中执行此操作,我会通过为悬停的东西创建一个组件来处理这个问题:

function MyImage({src, header}) {
    const [ref, hovered] = useHover();
    return (
        <div className="row imageSpace">
          {hovered && <h1>{header}</h1>}
          <img
            ref={ref}
            className="image"
            alt="fall"
            src={src}
          />
        </div>
    );
}

然后使用该组件:

return (
  <Wrapper>
    <Styles className="row">
      <Div className="col-xs-4">
        {data.map(item =>
          <MyImage
            key={item.sys.id}
            src={item.fields.image.file.url}
            header={item.fields.name}
          />
        )}
      </Div>

(显然,如果你愿意,可以让更多的道具可配置。)

【讨论】:

  • 这很棒。感觉很亲近。但图像组件无权访问项目,我收到错误“'项目'未定义”。
  • @WesleyBonneville - 我只是错过了它需要的道具,不知何故我在h1 中没有看到它...
  • @WesleyBonneville - 我已经修好了。
  • 成功了!我真的很喜欢这个解决方案。非常感谢,效果很好。
【解决方案2】:

作为一般规则,当您有一个带有Array.map() 的父项以及每个数组项的功能时,请将这些项重构为一个单独的组件(我的代码中为ImageRow)。

在这种情况下,您不需要使用 refs 来处理事件,因为 React 可以为您处理。与其从useHover 返回一个引用,不如返回一个带有事件处理程序的对象,并将其传播到组件上。

const { useState, useMemo } = React;

const useHover = () => {
  const [hovered, setHovered] = useState(false);
  
  const eventHandlers = useMemo(() => ({
    onMouseEnter: () => setHovered(true),
    onMouseLeave: () => setHovered(false)
  }), [setHovered]);
  
  return [hovered, eventHandlers];
};

const ImageRow = ({ name, url }) => {
  const [hovered, eventHandlers] = useHover();

  return (
    <div className="row imageSpace">
      {hovered && <h1>{name}</h1>}
      <img
        className="image"
        alt="fall"
        src={url}
        {...eventHandlers}
      />
    </div>
  );
};

const images = [{ id: 1, name: 'random1', url: 'https://picsum.photos/200?1' }, { id: 2, name: 'random2', url: 'https://picsum.photos/200?2' }, { id: 3, name: 'random3', url: 'https://picsum.photos/200?3' }];

const Wrapper = ({ images }) => (
  <div style={{ display: 'flex' }}>
  {images.map(({ id, ...props }) => <ImageRow key={id} {...props} />)}
  </div>
);

ReactDOM.render(
  <Wrapper images={images} />,
  root
);
h1 {
  position: absolute;
  pointer-events: none;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

【讨论】:

    猜你喜欢
    • 2020-10-08
    • 2022-01-23
    • 2018-07-01
    • 2011-12-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 2017-11-20
    • 2015-01-22
    相关资源
    最近更新 更多