繁体   English   中英

如何为 map 函数内的每次迭代分配一个新的 ref?

[英]How can I assign a new ref to every iteration inside a map function?

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

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

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

我怎样才能做到这一点?

这是我的 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>

如果可能的话,我会通过使用 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>

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

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

在这种情况下,您不需要使用 refs 进行事件处理,因为 React 可以为您处理。 不是从useHover返回 ref , 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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM