Closed lifegit closed 1 year ago
令人费解的是,这样的方案是可以的:
const Index = () => {
const ref = useRef() as React.MutableRefObject<HTMLDivElement>
const isHovering = useHover(ref);
console.log("isHovering", isHovering)
return (
<div ref={ref}>
<div>
<Counter />
</div>
</div>
);
};
提供个有问题的最小复现链接吧
import {useHover} from 'ahooks'; import {ReactNode, useRef, useState} from 'react'; import {Button} from "antd"; const Counter = () => { const [state, setState] = useState(0); return ( <div> <Button onClick={()=>setState(v=>v+1)}>+ {state}</Button> </div> ); }; const Index = () => { const ref = useRef() as React.MutableRefObject<HTMLDivElement> const isHovering = useHover(ref); console.log("isHovering", isHovering) const Action = ({children}: { children: ReactNode}) => ( <div> {children} </div> ); return ( <div > <Action> <Counter /> </Action> </div> ); }; export default Index;
示例代码没有复现哦~
https://github.com/alibaba/hooks/assets/38221479/83f42b4c-8592-4e0d-8cdf-358fba2f0129
Hi, lifegit.
It seems that this issue is a bit vague and lacks some necessary information.
看起来这条 issue 描述得有些模糊,缺少一些必要的信息。
不好意思。在示例中有个错误,忘了将ref挂载到div中,现已修改过来。 复现 repo:https://github.com/lifegit/test-ahhoks-userhover
这是正常逻辑,hover 完不 rerender 你的组件怎么获取到新的状态呢? @lifegit
@lifegit
useHover
是没问题的,问题在于你的使用问题。
一句话解释就是:父组件重渲染引起嵌套的子组件全新渲染了。
详细点解释就是:useHover 引起 Index 重渲染,导致 Action 的引用变了,Action 变成了全新的组件又导致 Action 和 Counter 都全新渲染。
这就是为什么很多人不推荐写嵌套的函数组件,因为有坑(当你知道坑以及解决办法时,还是可以用一用的)。
解决办法:
ref
放在 Counter
组件里:import { useHover } from 'ahooks';
import React, { useRef, useState } from 'react';
import type { ReactNode } from 'react';
import { Button } from 'antd';
const Counter = () => {
// 注意 ref 放在了这里
const ref = useRef<HTMLDivElement>(null);
const isHovering = useHover(ref);
console.log('isHovering', isHovering);
const [state, setState] = useState(0);
return (
<div>
<Button ref={ref} onClick={() => setState((v) => v + 1)}>
+ {state}
</Button>
</div>
);
};
const Index = () => {
const Action = ({ children }: { children: ReactNode }) => <div>{children}</div>;
return (
<div>
<Action>
<Counter />
</Action>
</div>
);
};
export default Index;
直接上示例:
现象
上述代码当点击button时,计数器正常增加,当移出鼠标时,计数器清零了(重新 render)。
解决方法
达成效果:鼠标移出计数器的值也不会改变。
-- 选择1: 移除 ref 或 useHover
-- 选择2: Action 组件移动到外面
困惑
这很令人很痛苦困惑,看起来 react vdom diff 失败了,导致鼠标移出就 render,但只是监听一下鼠标, 这是为什么呢?