首页 > 解决方案 > 如何在功能性 React 组件中创建静态函数?

问题描述

我正在尝试在功能性 React 组件中添加和删除事件侦听器。监听器添加得很好,但在被要求时不会被删除。我认为问题是我引用的函数在handlemousemove每个组件渲染时都会重新创建,因此当 removeEventListener 尝试删除它时,它与 addEventListener 添加它时的函数引用不同。

我尝试handlemousemove移出组件,但它需要访问组件中生成的 setState 挂钩。

const handleMouseMove = e => {
    setYOffset(e.clientY-280)
    setXOffset(e.clientX-350)
}

const followMouse = () => {
    if (isFollowingMouse){
        setIsFollowingMouse(false)
        document.removeEventListener("mousemove", handleMouseMove)
    } else {
        setIsFollowingMouse(true)
        document.addEventListener("mousemove", handleMouseMove)
    }
}

...

<button name="mouse" onClick={followMouse}>
    Follow Mouse
</button>

所有执行分支都在此处命中,但document.removeEventListener("mousemove", handleMouseMove)实际上并未删除事件侦听器。

有没有办法在功能组件中使用“静态方法”?这甚至是这里的问题吗?

这是包含整个代码的代码沙箱链接:https ://codesandbox.io/s/pzrwh

标签: javascripthtmlreactjs

解决方案


旧的方法是使用渲染道具,但现在钩子已经到来,这是一个更好的解决方案

const MyComponent = (props) => {
    const [isFollowingMouse, setIsFollowingMouse] = React.useState(false);
    const [xOffset, setXOffset] = React.useState(0);
    const [yOffset, setYOffset] = React.useState(0);
    
    const handleMouseMove = e => {
        if (isFollowingMouse) {
            setYOffset(e.clientY-28);
            setXOffset(e.clientX-35);
        }
    };

    const followMouse = () => {
        setIsFollowingMouse(!isFollowingMouse);
    }

    const styles = {
        'cat': {
            'backgroundColor': 'red',
            'height': '20px',
            'position': 'absolute',
            'left': xOffset,
            'top': yOffset,
            'width': '20px',
            'display': isFollowingMouse ? 'block' : 'none'
        }
    };

    return (
      <div style={{ 'height': '100%' }} onMouseMove={handleMouseMove}>
        <div style={ styles.cat }>C</div>
        <button name="mouse" onClick={followMouse}>
          Follow Mouse
        </button>
      </div>
    )
}



ReactDOM.render(<MyComponent />, document.getElementById('root'));
html,
body,
#root {
    height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="root"></div>


推荐阅读