我试图在React中的图标中添加一个事件侦听器,但它不起作用.我的代码:

const handleKey = (event) => {
    console.log(event);
}

<MdOutlinePause onKeyDown={handleKey} />

我在同一个按钮上也有一个onClick处理程序,可以正常工作,所以我真的很困惑onKeyDown为什么不能启动.感谢任何人能提供的帮助!

推荐答案

如果要将onKeyDown添加到某个元素,则需要专注才能工作.

我们可以通过添加tabindex属性使MdOutlinePause组件可以聚焦.这将允许你通过点击标签或点击图标来获得焦点.元素看起来像这样:

<MdOutlinePause tabIndex={0} onKeyDown={handleKey} />

如果要检测关键事件without,必须聚焦元素you will need to attach an event listener.我们可以用useEffect来实现这一点,所以这发生在mount上,我们将把事件监听器连接到window,这样不管哪个元素有焦点,它都可以工作:

  /// Don't copy and paste this - see below
  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);
    });
  }, []);
  /// Don't copy and paste this - see below

这允许您检测键盘事件,这很好,但有一个问题:the eventListener gets added again whenever the page mounts,但永远不会被删除.因此,您可能会遇到函数在每次按键时被多次调用的问题.

我们可以通过删除return from useEffect中的事件侦听器来解决这个问题.这就是我们如何指定一个函数,让useEffect clean up在其自身之后.这确保了我们的useEffect一次不会添加多个"按键"事件侦听器:

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, []);

这是example on codesandbox美元

如果您不需要访问handleKeyPress函数中的状态,这将非常有用.


当用户执行某个操作时,通常需要对状态变量执行一些操作,如果我们需要访问更新的状态,那么我们会遇到一个问题:我们将handleKeyPress附加到事件侦听器onMount,函数永远不会更新,因此它将始终使用状态的初始版本.This codesandbox说明了这个问题.

我们可以通过为useEffect将handleKeyPress添加到dependencies数组来解决这个问题,但这会导致我们的事件侦听器被删除,并在每个渲染中重新添加,因为handleKeyPress将在每个渲染中更新.更好的解决方案是使用handleKeyPress更新use the 100 pattern,这样它只在实际需要时更新(当它所依赖的状态更新时).我们还希望将handleKeyPress添加到useEffect依赖项数组中,以便在handleKeyPress函数更改时创建一个新的事件侦听器:

  const handleKeyPress = useCallback((event) => {
    // do stuff with stateVariable and event
  }, [stateVariable]);

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, [handleKeyPress]);

现在一切都适当地更新了!在codesandbox上有Here's a full example个.


还有一个解决方案可以让您以最简单的方式访问状态.缺点是,您可以访问的唯一状态变量(具有更新的值)将是您正在更新的状态变量,因此此解决方案是情境性的.要访问其他状态变量,必须使用上面的解决方案.

通过passing a function到useState,我们可以访问前一个状态作为函数的第一个参数.这允许一种更简单的方法,如下面和this codesandbox中所示.

  const [text, setText] = useState("");

  const handleKeyPress = event => {
    setText(previousText => `${previousText}${event.key}`);
  };

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, []);

Javascript相关问答推荐

为什么我的第二个OnClick Isloading值在TEK查询Mutations 查询中不起作用?

fetch在本地设置相同来源的cookie,但部署时相同的代码不会设置cookie

react 路由加载程序行为

具有相同参数的JS类

我在这个黑暗模式按钮上做错了什么?

Phaser框架-将子对象附加到Actor

嵌套异步JavaScript(微任务和macrotask队列)

在我的html表单中的用户输入没有被传送到我的google表单中

无法使用单击按钮时的useState将数据从一个页面传递到另一个页面

当id匹配时对属性值求和并使用JavaScript返回结果

让chart.js饼图中的一个切片变厚?

为什么JPG图像不能在VITE中导入以进行react ?

MongoDB受困于太多的数据

如何访问此数组中的值?

为什么NULL不能在构造函数的.Prototype中工作

是否设置以JavaScript为背景的画布元素?

如何在Java脚本中并行运行for或任意循环的每次迭代

当达到高度限制时,如何裁剪图像?使用html和css

在此div中添加一个类,并在一段时间后在Java脚本中将其删除

JavaScript -如何跳过某个字符(S)来打乱字符串中的字符