[英]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.