Прикрепление события к документу, которое зависит от условно отображаемого элемента в React

У меня есть элемент ввода, который отображается в зависимости от состояния.

render() {
const {
  isNameInputVisible,
  name
} = this.state;

return (

    <div>
      {isNameInputVisible ? (
        <input
          onChange = {this.handleNameChange}
          ref = {this.nameInput}
          type = "text"
          value = {name}
        />
      ) : (
        <h1
          className = "list-header__heading"
          onClick = {this.handleNameInputVisibility}
        >
          {name}
        </h1>
      )}
    </div>
)

По сути, я хочу прослушать щелчок по документу, чтобы скрыть ввод всякий раз, когда пользователь щелкает за пределами этого элемента ввода.

Прямо сейчас я делаю это:

  componentDidMount() {
    document.addEventListener('mousedown', this.handleClick);
  }


  handleClick = event => {
      //do some logic
  };

Но мне было интересно, правильный ли это способ, потому что событие существует и срабатывает, даже когда элемент не отображается.

Итак, я пробовал это:

componentDidUpdate () {
   const {isNameInputVisible} = this.state;
    isNameInputVisible &&  document.addEventListener('mousedown', this.handleClick);
}

Но это не работает.

Вопрос 1: Как правильно прикреплять события к документу, когда он зависит от других условно отображаемых элементов??

Вопрос 2: Каков правильный способ прикрепления событий, например, таких как нажатие выхода, для закрытия диалогов, которые о и т.д.??

Добавьте прослушиватель в componentDidmount. Проверьте target в обработчике. Обязательно удалите слушателя в componentWillUnmount

charlietfl 08.04.2019 15:49

вот как я это делаю прямо сейчас :) Но обработчик срабатывает даже тогда, когда он мне не нужен, потому что Input не виден. Вот почему я задаюсь вопросом, правильный ли это путь?

p7adams 08.04.2019 15:50

Можно сделать ввод компонентом

charlietfl 08.04.2019 15:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
3
1 122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно добавить прослушиватель событий в метод componentDidMount, только если ссылка на условно визуализируемый элемент существует. Вы можете узнать, была ли ссылка прикреплена к элементу, используя this.refName.current.

Самое главное здесь то, что элемент input получает свои собственные методы жизненного цикла вместо того, чтобы делиться ими с более крупным компонентом. Переместив элемент input в его собственный компонент с его собственными методами жизненного цикла, эти методы будут срабатывать только при создании и удалении input.

// App.jsx
import React from "react"
import ReactDOM from "react-dom"

import CustomInput from "./CustomInput"

class App extends React.Component {
  constructor(props) {
    super(props)
    this.inputRef = React.createRef()
    this.toggleInput = this.toggleInput.bind(this)
    this.state = {
      inputVisible: false
    }
  }

  toggleInput(e) {
    this.setState(prevState => ({
      inputVisible: !prevState.inputVisible
    }))
  }

  render() {
    const { inputVisible } = this.state

    return (
      <div>
        <input type = "button" value = "toggle input" onClick = {this.toggleInput} />
        { inputVisible
          ? <CustomInput />
          : <p>Input is not visible</p>
        }
      </div>
    )
  }
}

const rootElement = document.getElementById("root")
ReactDOM.render(<App />, rootElement)
// CustomInput.jsx
import React from "react"

export default class CustomInput extends React.Component {
  constructor(props) {
    super(props)
    this.inputRef = React.createRef()
  }

  componentDidMount() {
    this.inputRef.current &&
      document.addEventListener("mousedown", this.handleClick)
  }

  componentWillUnmount() {
    document.removeEventListener("mousedown", this.handleClick)
  }

  handleClick(e) {
    console.info("clicked")
  }

  render() {
    return (
      <input type = "text" ref = {this.inputRef} />
    )
  }
}

Попробуйте здесь

Так не пойдет. как по умолчанию. Ввод невидим, поэтому react не создаст на него ссылку. Я пробовал тот же подход в componentDidMount(). Вот так: componentDidMount() { this.inputRef.current && document.addEventListener()..... }, но при таком подходе, даже когда состояние было обновлено с isInputVisible до true, eventListener не был прикреплен к документу.

p7adams 09.04.2019 07:25

Это связано с тем, что ссылку необходимо прикрепить к условному элементу с помощью методов жизненного цикла компонента, которые вызываются после создания входных данных. Как только вы переместите элемент ввода в его собственный компонент с его собственными методами жизненного цикла, он отлично заработает. Я обновлю свой ответ этим.

Adam 09.04.2019 07:45

Другие вопросы по теме