【问题标题】:Dynamically created element is not firing click event in React [closed]动态创建的元素没有在 React 中触发点击事件 [关闭]
【发布时间】:2020-10-27 02:31:56
【问题描述】:

我有许多名为 infoopts 的元素,它们只是一个 html i 标签,我在点击时附加了一个事件侦听器,以便我可以更改它们的样式(背景颜色)。当我点击一个按钮时,这些是动态生成的。我已经尝试了一百万件事,但由于某种原因,它们都不会触发点击事件。 这是我尝试过的:

    useEffect(() => {
    const infoopts = document.querySelectorAll('.infoopts')
        infoopts.forEach(el => {
          el.addEventListener('click', function(e) {
              console.log('clicked') //never logs this 
              el.style.background = 'red'
          })
        })
  },[])

控制台甚至没有记录点击事件。这应该是一个业余问题。为什么不创建点击事件?

我不使用 React 的 2 个原因:

  1. 我还想为其相邻元素设置样式,onClick 只会设置该元素的样式
  2. 如果我使用状态,它将更改我所有具有 infoopts 类的元素,我只想设置被点击的元素及其邻居的样式(状态是全局的)

【问题讨论】:

  • 您是否有理由不使用 react 为您执行此操作?我认为安装组件时.infoopts 不会存在,因此您的querySelectorAll 什么也找不到。
  • 我刚刚做了。这就是为什么我使用香草来做到这一点。但是香草不起作用
  • 您的问题有点难以想象,请在代码沙箱或 github 存储库中提供可重现的示例
  • 您可以在谷歌搜索的任何反应待办事项列表示例中找到如何跟踪所选项目的示例,它基本上只是在父组件中有一个项目数组,在这种情况下是一个数组infoopts 元素
  • 是的,这听起来绝对像一个待办事项列表

标签: javascript reactjs events


【解决方案1】:

您问题中代码的问题是,在安装此组件时,.infoopts 甚至可能不存在。在这种情况下,querySelectorAll 将一无所获,并且您的事件处理程序将永远不会触发,因为它从未附加到任何东西。


在不知道数据来源或组件层次结构的情况下,下面是一个简单实现的可能示例。

保持某些本地组件状态以确定列表中的哪个项目被选中,然后从该状态呈现 UI。

渲染的 DOM 节点只是组件状态的反映。要更新任何 DOM 节点,只需更新该状态即可。

import React, { useState } from "react";

export default function App() {
  const [items, setItems] = useState([
    { title: "foo", selected: false },
    { title: "bar", selected: false },
    { title: "buzz", selected: false },
    { title: "foo", selected: false },
    { title: "bar", selected: false },
    { title: "buzz", selected: false },
    { title: "foo", selected: false },
    { title: "bar", selected: false },
    { title: "buzz", selected: false }
  ]);

  const handleClick = (i) => {
    const updated = [...items];
    updated[i].selected = !items[i].selected;
    setItems(updated);
  };

  const determineBgColor = (i) => {
    const itemIsSelected = items[i].selected;
    const neighbourIsSelected =
      items[i - 1]?.selected || items[i + 1]?.selected;

    if (itemIsSelected) {
      return "darkred";
    } else if (neighbourIsSelected) {
      return "bisque";
    }
    return "darksalmon";
  };

  return (
    <div className="App">
      <ul>
        {items.map((item, i) => (
          <li key={i}>
            <button
              style={{ background: determineBgColor(i) }}
              onClick={() => handleClick(i)}
            >
              {item.title}
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}


或者,状态可能已经保存在父组件中。在这种情况下,它可能会作为 prop 传递到此组件中,并且此组件只是根据该 prop 中数据的值进行渲染。

然后你需要找到一种方法来更新父组件中的状态,并且更改将从父组件流向子组件,并且渲染的 DOM 将相应地更新。

无论哪种方式,都适用相同的原则。使用 React 时,您的目标应该是编写对它们的状态和道具反应的声明性组件,而不是试图自己强制影响 DOM。


强烈建议您阅读https://reactjs.org/docs/thinking-in-react.html(如果您还没有阅读的话)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-05
    • 2012-07-28
    • 2023-03-08
    • 1970-01-01
    • 2012-12-07
    • 2018-11-13
    • 2012-08-18
    • 2014-05-01
    相关资源
    最近更新 更多