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

#javascript #reactjs #events #ecmascript-6

#javascript #reactjs #Мероприятия #ecmascript-6

Вопрос:

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

 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 amp;amp;  document.addEventListener('mousedown', this.handleClick);
}
  

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

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

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

Комментарии:

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

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

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

Ответ №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 amp;amp;
      document.addEventListener("mousedown", this.handleClick)
  }

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

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

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

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

Комментарии:

1. Это не сработает. как от deafult. Ввод невидим, поэтому react не создаст ссылку на него. Я попробовал ту же самую оценку в componentDidMount(). Вот так: componentDidMount() { this.inputRef.current amp;amp; document.addEventListener()….. } но при таком подходе, даже когда состояние было обновлено до значения isInputVisible равным true, EventListener не был прикреплен к документу.

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