Как обрабатывать события в React приложении

2 года назад·2 мин. на чтение

В этой статье рассмотрим как обработать события в React, а также о том, почему мы связываем ключевое слово `this` в классовых компонентах React.

В JSX нам нужно обернуть выражения JavaScript фигурными скобками { }. Обычный JavaScript:
<button onclick="hitMe()">hit me</button>
В ReactJS:
<button onClick={hitMe}>hitme</button>
Рассмотрим подробнее, как присоединить обработчики событий в функциональных и классовых компонентах.

Функциональные компоненты

function Button() {
  function handleClick() {
    alert('some one clicked me')
  }
  
  return (
    <button onClick={handleClick}>Click me</button>
  )
}
В React нам нужно передать функцию обработчика событий.

Передача аргументов

Мы также можем передавать аргументы в функции обработчика событий, подобные этой.
function Button() {
  function handleClick(name) {
     alert(name)
  }

  return (
    <button onClick={()=>handleClick('react')}>Click me</button>
  )
}

Классовые компоненты

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 0
    }
  }

  handleInc(){
    this.setState({
      num: this.state.num+1
    })
  }

  render(){
    return (
       <div>
        <h1>Counter</h1>
        <h3>{this.state.num}</h3>
        <button onClick={this.handleInc.bind(this)}>Increment</button>
      </div>
    )
  }
}
В компонентах на основе классов нам нужно привязать this к классу, иначе this будет привязано к global window object или в строгом режиме this будет undefined. Мы можем решить эту проблему с помощью стрелочных функций, потому что в стрелочных функциях this будет привязано к его внешнему контексту выполнения. Давайте модифицируем приведенный выше компонент с помощью стрелочных функций.
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 0
    }
  }

  handleInc() {
    this.setState({
      num: this.state.num+1
    })
  }

  render(){
    return (
       <div>
        <h1>Counter</h1>
        <h3>{this.state.num}</h3>
        <button onClick={()=>this.handleInc()}>Increment</button>
      </div>
    )
  }
}

Второй способ использования class fields syntax

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 0
    }
  }

  // стрелочная функция
  handleInc = () => {
    this.setState({
      num: this.state.num+1
    })
  }

  render() {
    return (
       <div>
        <h1>Counter</h1>
        <h3>{this.state.num}</h3>
        <button onClick={this.handleInc}>Increment</button>
      </div>
    )
  }
}

Объект события

Мы также можем использовать объект события таким образом в react.
function Link(){

  function handleClick(e){
     console.log(e);
     e.preventDefault();
  }

  return (
      <a href="#" onClick={handleClick} >Click me</a>
  )
}

Проп key для пересоздания компонента в ReactJS

2 года назад·2 мин. на чтение

Знали ли вы, что проп key может быть полезен не только при рендеринге списка компонентов. Проп key можно использовать и для того чтобы сбросить состояние одного компонента.

Что такое проп key в ReactJS?

Это специальный проп, который может быть добавлен к любому компоненту. Он помогает механизму reconciliation (согласование), упрощая сравнение компонентов. Типичный сценарий использования key - добавление его в компоненты списка. Он нужен для того чтобы React понимал, какой компонент списка был добавлен, удален или изменен.
const notes = [
  {
    id: 1,
    title: 'React hooks',
  },
  {
    id: 2,
    title: 'JSX',
  },
  {
    id: 3,
    title: 'Redux',
  },
];

const NotesList = ({ notes, onClick }) => {
  return (
    <div className="notes-list">
      {notes.map((note) => (
        <p
          className="notes-list__item"
          key={note.id}
          onClick={() => onClick(note)}
        >
          {note.title}
        </p>
      ))}
    </div>
  );
};

Проп key работает и вне списков

Проп key может быть добавлен к абсолютно любому компоненту для того, чтобы сбросить нежелательное состояние этого компонента. Например, в списке заметок есть поле для ввода текста. Если просто добавить это поле и ввести в него текст, то при выборе новой заметки слева - текст будет сохраняться. И, предположим, при выборе заметки мы хотим очистить это поле. список заметок в приложении ReactJS
function App() {
  const [activeNote, setActiveNote] = useState();

  const handleClick = (note) => {
    setActiveNote(note);
  };

  return (
    <div className="notes-container">
      <NotesList notes={notes} onClick={handleClick} />
      <Note title={activeNote?.title} />
    </div>
  );
}
const Note = ({ title }) => {
  const [text, setText] = useState();

  const handleChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div className="note">
      <p>{title}</p>
      <textarea
        className="note-textarea"
        value={text}
        onChange={handleChange}
      />
    </div>
  );
};
Это можно сделать, например, добавив проп text в компонент Note. И далее очищать его при изменении состояния activeNote. Но изменение компонентов может быть невозможным, если мы используем компоненты из third-party библиотеки.

Сброс состояние экземпляра компонента

Проп key помогает React идентифицировать компонент. Его также можно использовать, чтобы сообщить React, что идентификатор компонента изменился и это вызовет полное повторное создание этого компонента. Добавим key={activeNote?.id} к компоненту <Note />.
// ...
  return (
    <div className="notes-container">
      <NotesList notes={notes} onClick={handleClick} />
      <Note title={activeNote?.title} key={activeNote?.id} />
    </div>
  );
}
Теперь, при изменении key React пересоздаст компонент <Note />.

Влияние на производительность

Хотя это хороший прием, который уменьшает количество кода, важно иметь ввиду, что этот подход заставляет React пересоздавать весь экземпляр компонента. В примере выше большая часть компонента <Note /> будет перерисована в любом случае при изменении activeNote. Поэтому в этом случае это достаточно хорошее решение. В реальных приложениях нужно ограничивать добавление key к одиночным компонентам вне списков, а также избегать добавления key на компоненты верхнего уровня. Это может стать причиной проблем с производительностью, которые трудно обнаружить.