簡體   English   中英

React 中點擊子元素調用父事件監聽器

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

我正在做一個搜索輸入,人們可以在其中尋找技能,然后從選項中選擇一項技能。 但是,當我單擊任何選項時,它會調用父元素的事件偵聽器( onBlur={() => setIsFocus(false)} )。 當我刪除此事件偵聽器時,它會添加一項新技能,但當它存在時,它不會運行附加到子元素的 function。

我嘗試將e.stopPropagtion()添加到子元素中,但沒有用。

我的代碼:

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

技能建議列表組件:

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

使用 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>
      ))}

另外,讓我解釋一下為什么這里需要 onMouseDown 。 當您單擊列表時,在 onClick 運行之前它會變模糊並且 function 不再可用。 因此,當您使用 onMouseDown 時,它會首先運行 addSkill function 然后對其進行模糊處理。 希望它會起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM