React onClick - передать событие с параметром

93

Без параметра

function clickMe(e){
  //e is the event
}

<button onClick={this.clickMe}></button>

С параметром

function clickMe(parameter){
  //how to get the "e" ?
}
<button onClick={() => this.clickMe(someparameter)}></button>

Я хочу получить event. Как я могу это получить?

IMOBAMA
источник

Ответы:

166

Попробуй это:

<button onClick={(e) => {
     this.clickMe(e, someParameter)
}}>Click Me!</button>

И в вашей функции:

function clickMe(event, someParameter){
     //do with event
}
Джйоти Бабу Араджа
источник
2
Это дало мне ошибку eslint ( eslint.org/docs/rules/arrow-parens.html ) Я заключил параметры функции в круглые скобкиonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm 08
1
Да @kretzm Если мы не указываем фигурные скобки, оно действует как возвращаемое выражение, когда это одна строка, иначе мы должны использовать фигурные скобки для переноса в тело функции.
Джиоти Бабу Араджа
4
Я просто хочу добавить, что это не рекомендуемый синтаксис. Из документации responsejs: проблема с этим синтаксисом заключается в том, что каждый раз, когда отображается кнопка, создается другой обратный вызов. В большинстве случаев это нормально. Однако, если этот обратный вызов передается как опора для более низких компонентов, эти компоненты могут выполнить дополнительный повторный рендеринг. Обычно мы рекомендуем привязку в конструкторе или использование синтаксиса полей класса, чтобы избежать такого рода проблем с производительностью. Более подробная информация на reactjs.org
northernwind
1
@Виктор. Да ты прав. Но если вы хотите, чтобы контекст вашего родителя был внутри вашего обратного вызова, вам нужно иметь разные обратные вызовы для каждого рендера. На самом деле, я думаю, это компромисс.
Джиоти Бабу Араджа
@JyothiBabuAraja Я думаю, что лучшее решение - использовать data-*атрибуты в HTML5. Пожалуйста, смотрите мой ответ ниже для более подробной информации.
Гарри Чанг
34

С ES6 вы можете сделать это более коротким способом:

const clickMe = (parameter) => (event) => {
    // Do something
}

И используйте это:

<button onClick={clickMe(someParameter)} />
Минь Кха
источник
Это также решает проблему создания нового обратного вызова? stackoverflow.com/questions/42597602/…
Отани Сюдзо
1
в дополнение к этому вы можете отправить несколько параметров. const clickMe = (параметр1, параметр2) => (событие) => {// Сделайте что-нибудь}
AhuraMazda
1
Он также запускается, когда ваш компонент монтируется, ваш код должен быть:onClick={(e) => clickMe(someParameter)(e)}
Александр Ким
Как и в случае с clickMe, вы также можете уничтожить событие, даже если вы не определяете его как параметр.
Минь Кха,
Спасибо за это. Оно работает. Но почему const clickMe = (parameter) => (event) => {...} вместо этого const clickMe = (parameter) => {...}?
zrna
16

Решение 1

function clickMe(parameter, event){
}

<button onClick={(event) => {this.clickMe(someparameter, event)}></button>

Решение 2 Использование функции привязки считается лучше, чем использование функции стрелки в решении 1. Обратите внимание, что параметр события должен быть последним параметром в функции-обработчике.

function clickMe(parameter, event){
}

<button onClick={this.clickMe.bind(this, someParameter)}></button>
Бенс Дергез
источник
+1 для параметра события, который является последним в решении №2. Мне потребовалась вечность, чтобы понять, что я делаю неправильно, я, должно быть, пропустил причину где-то в документации.
abelito
5

Чтобы полностью решить проблему создания нового обратного вызова, используйте data-* атрибуты в HTML5 - лучшее решение IMO. Поскольку в конце дня, даже если вы извлекаете подкомпонент для передачи параметров, он все равно создает новые функции.

Например,

const handleBtnClick = e => {
  const { id } = JSON.parse(e.target.dataset.onclickparam);
  // ...
};

<button onClick={handleBtnClick} data-onclickparam={JSON.stringify({ id: 0 })}>

См. Https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes для использования data-*атрибутов.

Гарри Чанг
источник
Мне нравится такой подход. Просто и чисто
marknt15
5

Карринг с примером ES6:

const clickHandler = param => event => {
  console.log(param); // your parameter
  console.log(event.type); // event type, e.g.: click, etc.
};

Наша кнопка, которая переключает обработчик:

<button onClick={(e) => clickHandler(1)(e)}>Click me!</button>

Если вы хотите вызвать это выражение функции без объекта события, вы бы назвали его так:

clickHandler(1)();

Кроме того, поскольку в реакции используются синтетические события (оболочка для собственных событий), существует функция объединения событий , что означает, что если вы хотите использовать свой eventобъект асинхронно, вам придется использовать event.persist():

const clickHandler = param => event => {
  event.persist();
  console.log(event.target);
  setTimeout(() => console.log(event.target), 1000); // won't be null, otherwise if you haven't used event.persist() it would be null.
};

Вот живой пример: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark

Александр Ким
источник
Почему мне все еще нужно иметь event.persist()с собой, console.log(event)но мне это не нужно console.log(event.target)?
Исаак Пак,
1
Прочтите это: responsejs.org/docs/events.html#event-pooling
Александр Ким,
В этом контексте быстрее использовать обычную функцию, получающую 2 параметра, чем каррирование. вы можете запустить тестовый тест в jsben.ch
ncesar
@ncesar Как настроить React в jsben.ch? Разместите свой тест плз.
Исаак Пак,
@IsaacPak jsben - это простой инструмент для тестирования кодов javascript. Вы в значительной степени размещаете два разных образца кода и сравниваете их скорость. Вам не нужно помещать весь код React, просто функцию, которая, по вашему мнению, может быть медленнее, и которую вы хотите протестировать. Кроме того, я всегда использую jsben.ch и jsbench.me на всякий случай. В контексте clickHandler вам нужно будет имитировать некоторые коды. Как будто let event;он не выдаст неопределенную ошибку.
ncesar