反应钩悬停效果

时间:2020-05-02 16:24:01

标签: reactjs react-hooks

我正在尝试使用react钩子使悬停效果 我根据一些教程编写了悬停功能

function useHover() {
  const [hovered, setHovered] = useState(false);

  const ref = useRef(null);

  const handleMouseOver = () => setHovered(true);
  const handleMouseOut = () => setHovered(false);

  useEffect(() => {
    const node = ref.current;
    if (node) {
      node.addEventListener("mouseover", handleMouseOver);
      node.addEventListener("mouseout", handleMouseOut);

      return () => {
        node.removeEventListener("mouseover", handleMouseOver);
        node.removeEventListener("mouseout", handleMouseOut);
      };
    }
  }, [ref]);

  return [ref, hovered];
}

但是如何使其在我的App功能中起作用

export default function App() {
  const [ref, isHovered] = useHover();

  const reactionItems = myObject.map(([key, value]) => (
    <li key={key} ref={ref}>
      {isHovered ? `${key} ${value.length > 1 ? "x " + value.length : ""}` : `${key} ${value.length > 1 ? "x " + value.length : ""} ${value}`}
    </li>
  ));


return (
    <div className="App">
      <h1>{string}</h1>
      <h2>Reactions</h2>
      <ul>{reactionItems}</ul>
    </div>
  );

} 

我只能在false状态下看到它,所以第二种选择没有悬停效果

2 个答案:

答案 0 :(得分:2)

使用React's events' system,而不要使用DOM。此外,每个项目都应具有自己的事件处理程序和状态。

创建一个钩子,该钩子返回悬停状态和项目的事件侦听器。创建一个Item组件,并使用其定义中的钩子。渲染项目。

end
Ord

答案 1 :(得分:0)

做到这一点的一种方法是使用React的事件,只需确保让它更通用即可。

您遇到的问题之一是ref一次只能引用一个节点。而且ref永远不会更改依赖项,因此useEffect只会运行一次。

const { useState, useRef, useEffect, useCallback } = React;

function useHover() {
  const [hovered, setHovered] = useState({});

  const mouseOver = useCallback((event) => {
    const target = event.target;
    const key = target.getAttribute('data-key');
    setHovered((curState) => ({ ...curState, [key]: true }));
  }, []);

  const mouseOut = useCallback((event) => {
    const target = event.target;
    const key = target.getAttribute('data-key');
    setHovered((curState) => ({ ...curState, [key]: false }));
  }, []);

  return { mouseOver, mouseOut, hovered };
}

const object = { key1: 'test', key2: 'test2', key3: 'test3' };
const myObject = Object.entries(object);
const string = 'Header';
function App() {
  const { mouseOver, mouseOut, hovered } = useHover();

  const reactionItems = myObject.map(([key, value]) => (
    <li key={key} data-key={key} onMouseOver={mouseOver} onMouseOut={mouseOut}>
      {hovered[key]
        ? `${key} ${value.length > 1 ? 'x ' + value.length : ''}`
        : `${key} ${value.length > 1 ? 'x ' + value.length : ''} ${value}`}
    </li>
  ));

  return (
    <div className="App">
      <h1>{string}</h1>
      <h2>Reactions</h2>
      <ul>{reactionItems}</ul>
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector('#root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"/>

您还可以将列表项分离到它们自己的组件中,这将使您可以更轻松地使用useHover。