简体   繁体   English

React 中点击子元素调用父事件监听器

[英]Clicking on a child element calls a parent event listener in React

I am making a search input where people can look for skills and then choose a skill from the choices.我正在做一个搜索输入,人们可以在其中寻找技能,然后从选项中选择一项技能。 However, when I click on any of the options, it calls the event listener for the parent element ( onBlur={() => setIsFocus(false)} ).但是,当我单击任何选项时,它会调用父元素的事件侦听器( onBlur={() => setIsFocus(false)} )。 When I remove this event listener, it adds a new skill, but when it is there, it does not run the function that is attached to the child element.当我删除此事件侦听器时,它会添加一项新技能,但当它存在时,它不会运行附加到子元素的 function。

I tried to add e.stopPropagtion() to the child element, but it didn't work.我尝试将e.stopPropagtion()添加到子元素中,但没有用。

My Code:我的代码:

import { useRef, useState } from "react"

import fetchSkills from "../api"
import BaseInput from "../components/reusable/BaseInput"
import SkillsSuggestionList from "../components/solutions/SkillsSuggestionList"
import Icons from "../components/SvgIcons/Icons"
import { debounce } from "../utils/shared"

const SKILLS = [
  { name: "html" },
  { name: "css" },
  { name: "javascript" },
  { name: "bootstrap" },
  { name: "tailwind-css" },
  { name: "react" },
  { name: "vue" },
  { name: "angular" },
]

const SolutionForm = () => {
  const [skills, setSkills] = useState([])
  const [isFocus, setIsFocus] = useState(false)
  const selectRef = useRef(null)

  // fetch skills and render them in a SkillsSuggestionList component
  const handleSelectChange = async (e) => {
    const { value } = e.target

    if (value.length > 2) {
      const result = await fetchSkills(value)
      setSkills(result.items)
    }
  }

  const addSkill = (skill) => {
      setData({
        ...data,
        skills: [...data.skills, skill],
      })
    setIsFocus(false)
    setSkills([])
    selectRef.current.value = ""
  }

  return (
    <div>
      <div>
        <form onSubmit={handleSubmit}>
              <div
                key={input.name}
                onBlur={() => setIsFocus(false)} // this is a parent event listener
              >
                <div
                  key={input.name}
                >
                  <ul>
                    {data.skills.map((skill, index) => (
                      <li key={index}>
                          {skill}
                      </li>
                    ))}
                  </ul>
                  <BaseInput
                    onChange={debounce(handleSelectChange, 500)}
                    onFocus={() => setIsFocus(true)}
                    name={input.name}
                    innerRef={selectRef}
                  />
                </div>
                {isFocus && (
                  <SkillsSuggestionList
                    skills={skills.length > 0 ? skills : SKILLS}
                    addSkill={addSkill}
                  />
                )}
              </div>
        </form>
      </div>
    </div>
  )
}

export default SolutionForm

SkillSuggestionList component:技能建议列表组件:

const SkillsSuggestionList = ({ skills, addSkill }) => {
  return (
    <ul
      id="skills"
    >
      {skills.map((skill) => (
        <li
          onClick={(e) => { // this is a child event listener
            e.stopPropagation()
            addSkill(skill.name)
          }}
          key={skill.name}
        >
          {skill.name}
        </li>
      ))}
    </ul>
  )
}

export default SkillsSuggestionList

Using onMouseDown instead of onClick will do the trick.使用 onMouseDown 而不是 onClick 就可以了。

{skills.map((skill) => (
        <li
          onMouseDown={(e) => { // this is a child event listener
            // e.stopPropagation() <--- this won't be needed
            addSkill(skill.name)
          }}
          key={skill.name}
        >
          {skill.name}
        </li>
      ))}

Also, let me explain why onMouseDown is needed here.另外,让我解释一下为什么这里需要 onMouseDown 。 When you click the list, before onClick run it blurs down and the function is no longer available.当您单击列表时,在 onClick 运行之前它会变模糊并且 function 不再可用。 So when you use onMouseDown it will first run the addSkill function and then blur it.因此,当您使用 onMouseDown 时,它会首先运行 addSkill function 然后对其进行模糊处理。 Hop it will work.希望它会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM