React js onClick не може передати значення методу


638

Я хочу прочитати властивості значення onClick події. Але натискаючи на нього, на консолі я бачу щось подібне:

SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target

Мій код працює правильно. Під час запуску я бачу, {column}але не можу отримати його у події onClick.

Мій код:

var HeaderRows = React.createClass({
  handleSort:  function(value) {
    console.log(value);
  },
  render: function () {
    var that = this;
    return(
      <tr>
        {this.props.defaultColumns.map(function (column) {
          return (
            <th value={column} onClick={that.handleSort} >{column}</th>
          );
        })}
        {this.props.externalColumns.map(function (column) {
          // Multi dimension array - 0 is column name
          var externalColumnName = column[0];
          return ( <th>{externalColumnName}</th>);
        })}
      </tr>
    );
  }
});

Як я можу передати значення onClickподії в React js?


2
можливий дублікат прив’язки OnClick Event у React.js
WiredPrairie

2
Подумайте про використання самостійно замість цього. Це досить оманливо, оскільки це має бути синонімом "цього" (не важливо, правда, для кожного свого)
Dan

Використовуючи метод прив’язки та метод стрілки, ми можемо передати значення події
Onclick

Відповіді:


1285

Легкий шлях

Використовуйте функцію стрілки:

return (
  <th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);

Це створить нову функцію, яка викликає handleSortпотрібні параметри.

Кращий шлях

Витягніть його в підкомпонент. Проблема з використанням функції стрілки для виклику візуалізації полягає в тому, що вона буде створювати нову функцію щоразу, що призводить до непотрібних повторних візуалізацій.

Якщо ви створюєте підкомпонент, ви можете передавати обробник і використовувати реквізити в якості аргументів, які потім повторно відображатимуться лише тоді, коли реквізит зміниться (оскільки посилання обробника зараз ніколи не змінюється):

Підкомпонент

class TableHeader extends Component {
  handleClick = () => {
    this.props.onHeaderClick(this.props.value);
  }

  render() {
    return (
      <th onClick={this.handleClick}>
        {this.props.column}
      </th>
    );
  }
}

Основний компонент

{this.props.defaultColumns.map((column) => (
  <TableHeader
    value={column}
    onHeaderClick={this.handleSort}
  />
))}

Старий простий шлях (ES5)

Використовуйте .bindдля передачі потрібного параметра:

return (
  <th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);

7
react дає попередження, коли я використовую, як ваш код. Я змінюю свій код на onClick = {that.onClick.bind (null, column)}
користувач1924375

12
Як би ви скористалися цим <a>тегом, куди вам потрібно передати подію, для того, щоб використовуватиpreventDefault()
Simon H

38
@SimonH Подія буде передана як останній аргумент після аргументів, які ви передаєте через bind.
розмазати

47
Це не погано для продуктивності? не буде створена нова функція для кожного візуалізації?
AndrewMcLagan

13
@AndrewMcLagan Це так. Я знайшов це для опису правила та найефективнішого рішення.
Е. Сундін

140

Тут є приємні відповіді, і я погоджуюсь з @Austin Greco (другий варіант з окремими компонентами).
Є ще один спосіб, який мені подобається, каррінг .
Що ви можете зробити, це створити функцію, яка приймає параметр (ваш параметр) і повертає іншу функцію, яка приймає інший параметр (подія клацання в цьому випадку). тоді ви вільні робити з ним все, що завгодно.

ES5:

handleChange(param) { // param is the argument you passed to the function
    return function (e) { // e is the event object that returned

    };
}

ES6:

handleChange = param => e => {
    // param is the argument you passed to the function
    // e is the event object that returned
};

І ви будете використовувати це так:

<input 
    type="text" 
    onChange={this.handleChange(someParam)} 
/>

Ось повний приклад такого використання:

Зауважте, що цей підхід не вирішує створення нового примірника для кожного візуалізації.
Мені подобається такий підхід у порівнянні з іншими вбудованими обробниками, оскільки цей, на мою думку, більш стислий і читабельний.

Редагувати:
Як запропоновано в коментарях нижче, ви можете кешувати / запам'ятовувати результат функції.

Ось наївна реалізація:


12
Це має бути прийнятою відповіддю. Дійсно простий у виконанні, і вам не потрібно створювати будь-які інші компоненти або пов'язувати по-іншому. Дякую!
Тамб

29
Виглядає краще, але, з точки зору продуктивності, використання каррі насправді не допомагає, тому що якщо ви двічі викликаєте handleChange, з тим же парам, ви отримаєте дві функції, які двигун JS вважає окремими об'єктами, навіть якщо вони роблять те саме . Таким чином, ви все одно отримаєте повторну візуалізацію. Для забезпечення продуктивності вам потрібно буде кешувати результати handleChange, щоб отримати перевагу в продуктивності. LikehandleChange = param => cache[param] || (e => { // the function body })
travellingprog

6
Це ідеальна відповідь, якщо ви виконаєте пораду від @travellingprog
llioor

2
Хтось може надати посилання або пояснити, як працює цей механізм кешування? Дякую.
Садок Мтір

2
Красиво і акуратно!
Хатем Алімам

117

Сьогодні, за допомогою ES6, я думаю, що ми могли б використовувати оновлену відповідь.

return (
  <th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);

В основному, (для тих, хто не знає), оскільки onClickочікує переданої йому функції, bindпрацює, оскільки створює копію функції. Натомість ми можемо передавати вираз функції стрілки, який просто викликає потрібну нам функцію та зберігає this. Вам ніколи не потрібно зв'язувати renderметод у React, але якщо ви чомусь втрачаєте thisодин із своїх компонентних методів:

constructor(props) {
  super(props);
  this.myMethod = this.myMethod.bind(this);
}

10
Вам ніколи не потрібно пов'язувати, render()тому що це називається React. Якщо що-небудь, вам потрібно bindобробляти події, і лише тоді, коли ви не використовуєте стрілки.
Дан Абрамов

1
@DanAbramov Я вважаю, що ви правильні, але я включив його на всякий випадок - оновив приклад, який неявно не заохочує візуалізацію обов'язкових.
айкеру

3
Зверніть увагу, що також краще перейти propsдо super()або this.propsне буде визначено під час конструктора, що може заплутатись.
Дан Абрамов

2
Щоб досягти чого? Ви можете визначити обробник всередині функціонального компонента і передати його. Це буде різною функцією кожного рендерінгу, тому якщо ви визначили з профілером, що він надає вам проблеми з perf (і лише якщо ви справді впевнені в цьому!), Подумайте про використання класу.
Дан Абрамов

1
@ me-me Так, і якщо ви ввімкнули JavaScript, що кровоточить, в Babel вам слід просто оголосити властивості свого класу, як, foo = () => {...}а потім <button onClick={this.foo}...вказати єдину причину включення функції стрілки, якщо ви використовуєте babel таким чином, IMO, це якщо ви хочете зафіксувати якусь змінну, яка існує лише в області методу render () (події можна просто передавати і не застосовувати).
айкеру

73

[[h / t до @ E.Sundin за посилання на це в коментарі]

Верхня відповідь (анонімні функції або прив'язка) буде працювати, але це не найефективніше, оскільки створює копію обробника подій для кожного екземпляра, генерованого map()функцією.

Це пояснення оптимального способу зробити це за допомогою ESLint-plugin-react :

Списки предметів

Загальний випадок використання прив'язки у візуалізації - це при наданні списку, щоб мати окремий зворотний виклик для кожного елемента списку:

const List = props => (
      <ul>
        {props.items.map(item =>
          <li key={item.id} onClick={() => console.log(item.id)}>
            ...
          </li>
        )}
      </ul>
    );

Замість того, щоб зробити це таким чином, перетягніть повторний розділ у його власний компонент:

const List = props => (
      <ul>
        {props.items.map(item =>
          <ListItem 
            key={item.id} 
            item={item} 
            onItemClick={props.onItemClick} // assume this is passed down to List
           />
        )}
      </ul>
    );


const ListItem = props => {
  const _onClick = () => {
    console.log(props.item.id);
  }
    return (
      <li onClick={_onClick}>
        ...
      </li>
    );

});

Це пришвидшить візуалізацію, оскільки уникне необхідності створення нових функцій (за допомогою прив'язки дзвінків) для кожного рендеру.


Чи реагує виклик цих функцій при виклику / застосуванні, тоді, під кришкою, і уникає використання внутрішніх зв'язків?
aikeru

1
Чи є спосіб зробити це за допомогою компонента без громадянства?
Карлос Мартінес

2
@CarlosMartinez Добре око, я оновив приклад - в першу чергу вони повинні були бути функціональними компонентами без громадянства (SFC). Як правило, якщо компонент ніколи не використовується this.state, можна сміливо поміняти його на SFC.
Брендон

3
Гм, я не розумію, наскільки це ефективніше? Чи не буде функція ListItem викликатися кожен раз, і таким чином, функція _onClick буде створена для кожного візуалізації.
Маттіас Петтер Йоханссон

1
Я далеко не експерт, але, як я це розумію, у "правильному" шаблоні є лише один екземпляр обробника, і він передає опору для того, хто інший компонент називає його. У прикладі прив'язки (тобто, "неправильний" шаблон) є один екземпляр обробника для кожного інстанційного компонента. Це свого роду еквівалент пам’яті написання тієї самої функції тридцять разів віце-записати її один раз і викликати її там, де потрібно.
Брендон

25

Це мій підхід, не впевнений, наскільки це погано, прокоментуйте, будь ласка

У елементі, що можна натиснути

return (
    <th value={column} onClick={that.handleSort} data-column={column}>   {column}</th>
);

і потім

handleSort(e){
    this.sortOn(e.currentTarget.getAttribute('data-column'));
}

Це такий підхід, про який я думав, він трохи хиткий, але уникає створення нового компонента. Я не впевнений, що getAttribute є кращим чи гіршим, ніж це витягнути в окремий компонент.
kamranicus

2
Я думаю, що це гарне рішення, тому що це дуже просто. Але він працює лише зі значеннями рядків, якщо ви хочете, щоб об'єкт не працював.
Стефан L

Для об'єкта , вам потрібно буде зробити encodeURIComponent(JSON.stringify(myObj)), щоб потім розібрати його, JSON.parse(decodeURIComponent(myObj)). Що стосується функцій, я впевнений, що це не працює без eval або нової функції (), яких слід уникати. З цієї причини я не використовую атрибути даних для передачі даних у React / JS.
Солвітіг

Хочу додати, що я не використовую це часто і лише для незначних речей. Але зазвичай я просто створюю компонент і передаю дані в якості реквізиту до нього. Потім або обробляйте клацання всередині цього нового компонента, або передайте компоненту функцію onClick. Як пояснюється у відповіді Брендона
Сантьяго Рамірес

1
Доступ до набору даних можна отримати безпосередньо цим способом у сучасних браузерах (включаючи IE11): e.currentTarget.dataset.column
gsziszi

17

цей приклад може трохи відрізнятися від вашого. але я можу запевнити, що це найкраще рішення для цієї проблеми. Я цілими днями шукав рішення, яке не має проблем із продуктивністю. і нарешті придумав цей.

class HtmlComponent extends React.Component {
  constructor() {
    super();
    this.state={
       name:'MrRehman',
    };
    this.handleClick= this.handleClick.bind(this);
  }

  handleClick(event) {
    const { param } = e.target.dataset;
    console.log(param);
    //do what you want to do with the parameter
  }

  render() {
    return (
      <div>
        <h3 data-param="value what you wanted to pass" onClick={this.handleClick}>
          {this.state.name}
        </h3>
      </div>
    );
  }
}

ОНОВЛЕННЯ

у випадку, якщо ви хочете мати справу з об'єктами, які повинні бути параметрами. ви можете використовуватиJSON.stringify(object) для перетворення в рядок та додавання до набору даних.

return (
   <div>
     <h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
        {this.state.name}
     </h3>
   </div>
);

1
це не працює, коли передані дані є об’єктом
SlimSim

використовуйте JSON.stringify для виправлення проблеми. @SlimSim. що має зробити трюк
hannad rehman

Якщо вам потрібно використовувати JSON.stringify для цієї проблеми, то, ймовірно, це не правильний метод. Процес стрифікації займає багато пам’яті.
KFE

у більшості випадків ви передаєте ідентифікатор лише у вигляді парам і отримуєте деталі об'єкта на основі цього ідентифікатора від вашого вихідного об'єкта. і чому і як це займає багато пам’яті, я знаю, що JSON stringify повільний, але натискання Fn є асинхронним і не буде мати жодного або 0 ефекту на dom, колись побудований
hannad rehman


4

Ще один варіант, що не включає .bindабо ES6, - це використовувати дочірній компонент з обробником для виклику батьківського обробника з необхідними реквізитами. Ось приклад (а посилання на робочий приклад наведено нижче):

var HeaderRows = React.createClass({
  handleSort:  function(value) {
     console.log(value);
  },
  render: function () {
      var that = this;
      return(
          <tr>
              {this.props.defaultColumns.map(function (column) {
                  return (
                      <TableHeader value={column} onClick={that.handleSort} >
                        {column}
                      </TableHeader>
                  );
              })}
              {this.props.externalColumns.map(function (column) {
                  // Multi dimension array - 0 is column name
                  var externalColumnName = column[0];
                  return ( <th>{externalColumnName}</th>
                  );
              })}
          </tr>);
      )
  }
});

// A child component to pass the props back to the parent handler
var TableHeader = React.createClass({
  propTypes: {
    value: React.PropTypes.string,
    onClick: React.PropTypes.func
  },
  render: function () {
    return (
      <th value={this.props.value} onClick={this._handleClick}
        {this.props.children}
      </th>
    )        
  },
  _handleClick: function () {
    if (this.props.onClick) {
      this.props.onClick(this.props.value);
    }
  }
});

Основна ідея полягає в тому, щоб батьківський компонент передав onClickфункцію дочірньому компоненту. Дочірній компонент викликає onClickфункцію і може отримати доступ до будь-якого propsпереданого до неї (і event), що дозволяє використовувати будь-яке eventзначення або інші реквізити в батьківськихonClick функції.

Ось демонстраційний код CodePen, що показує цей метод у дії.


4

Здійснюючи альтернативну спробу відповісти на питання ОП, включаючи дзвінки e.preventDefault ():

Надане посилання ( ES6 )

<a href="#link" onClick={(e) => this.handleSort(e, 'myParam')}>

Функція компонента

handleSort = (e, param) => {
  e.preventDefault();
  console.log('Sorting by: ' + param)
}

4

Я усвідомлюю, що це досить пізно для вечірки, але я думаю, що набагато простіше рішення могло б задовольнити багато випадків використання:

    handleEdit(event) {
        let value = event.target.value;
    }

    ...

    <button
        value={post.id}
        onClick={this.handleEdit} >Edit</button>

Я припускаю, що ви також могли використовувати data-атрибут.

Простий, смисловий.


4

Просто створіть таку функцію

  function methodName(params) {
    //the thing  you wanna do
  }

і зателефонуйте в потрібне місце

<Піктограма onClick = {() => {methodName (theParamsYouwantToPass); }} />


3

Ви можете просто зробити це, якщо використовуєте ES6.

export default class Container extends Component {
  state = {
    data: [
        // ...
    ]
  }

  handleItemChange = (e, data) => {
      // here the data is available 
      // ....
  }
  render () {
     return (
        <div>
        {
           this.state.data.map((item, index) => (
              <div key={index}>
                  <Input onChange={(event) => this.handItemChange(event, 
                         item)} value={item.value}/>
              </div>
           ))
        }
        </div>
     );
   }
 }

3

Реалізація показує загальний підрахунок від об'єкта, передаючи підрахунок як параметр від основного до підкомпонентів, як описано нижче.

Ось MainComponent.js

import React, { Component } from "react";

import SubComp from "./subcomponent";

class App extends Component {

  getTotalCount = (count) => {
    this.setState({
      total: this.state.total + count
    })
  };

  state = {
    total: 0
  };

  render() {
    const someData = [
      { name: "one", count: 200 },
      { name: "two", count: 100 },
      { name: "three", count: 50 }
    ];
    return (
      <div className="App">
        {someData.map((nameAndCount, i) => {
          return (
            <SubComp
              getTotal={this.getTotalCount}
              name={nameAndCount.name}
              count={nameAndCount.count}
              key={i}
            />
          );
        })}
        <h1>Total Count: {this.state.total}</h1>
      </div>
    );
  }
}

export default App;

І ось SubComp.js

import React, { Component } from 'react';
export default class SubComp extends Component {

  calculateTotal = () =>{
    this.props.getTotal(this.props.count);
  }

  render() {
    return (
      <div>
        <p onClick={this.calculateTotal}> Name: {this.props.name} || Count: {this.props.count}</p>
      </div>
    )
  }
};

Спробуйте здійснити вище, і ви отримаєте точний сценарій того, як параметри передачі працюють у reactjs на будь-якому методі DOM.


3

Я написав компонент обгортки, який можна використовувати повторно для цієї мети, який спирається на прийняті тут відповіді. Якщо все, що вам потрібно зробити, це пропустити рядок, то просто додайте атрибут даних і прочитайте його з e.target.dataset (як це запропонували деякі інші). За замовчуванням мій обгортник зв’яжеться з будь-якою опорою, яка є функцією, і починається з "увімкнено" і автоматично передасть запит даних назад абоненту після всіх інших аргументів події. Хоча я не перевіряв його на продуктивність, це дасть вам можливість уникнути створення класу самостійно, і його можна використовувати так:

const DataButton = withData('button')
const DataInput = withData('input');

або для компонентів та функцій

const DataInput = withData(SomeComponent);

або якщо ви віддаєте перевагу

const DataButton = withData(<button/>)

заявити, що поза вашим контейнером (біля імпорту)

Ось використання в контейнері:

import withData from './withData';
const DataInput = withData('input');

export default class Container extends Component {
    state = {
         data: [
             // ...
         ]
    }

    handleItemChange = (e, data) => {
        // here the data is available 
        // ....
    }

    render () {
        return (
            <div>
                {
                    this.state.data.map((item, index) => (
                        <div key={index}>
                            <DataInput data={item} onChange={this.handleItemChange} value={item.value}/>
                        </div>
                    ))
                }
            </div>
        );
    }
}

Ось обгортковий код 'withData.js:

import React, { Component } from 'react';

const defaultOptions = {
    events: undefined,
}

export default (Target, options) => {
    Target = React.isValidElement(Target) ? Target.type : Target;
    options = { ...defaultOptions, ...options }

    class WithData extends Component {
        constructor(props, context){
            super(props, context);
            this.handlers = getHandlers(options.events, this);        
        }

        render() {
            const { data, children, ...props } = this.props;
            return <Target {...props} {...this.handlers} >{children}</Target>;
        }

        static displayName = `withData(${Target.displayName || Target.name || 'Component'})`
    }

    return WithData;
}

function getHandlers(events, thisContext) {
    if(!events)
        events = Object.keys(thisContext.props).filter(prop => prop.startsWith('on') && typeof thisContext.props[prop] === 'function')
    else if (typeof events === 'string')
        events = [events];

    return events.reduce((result, eventType) => {
        result[eventType] = (...args) => thisContext.props[eventType](...args, thisContext.props.data);
        return result;
    }, {});
}

2

Я маю нижче 3 пропозиції щодо цього на JSX onClick Events -

  1. Насправді нам не потрібно використовувати .bind () або стрілку у своєму коді. Ви можете просто використовувати у своєму коді.

  2. Ви також можете перемістити подію onClick від th (або ul) до tr (або li), щоб поліпшити продуктивність. В основному у вас буде n кількість "слухачів подій" для вашого n li елемента.

    So finally code will look like this:
    <ul onClick={this.onItemClick}>
        {this.props.items.map(item =>
               <li key={item.id} data-itemid={item.id}>
                   ...
               </li>
          )}
    </ul>

    // І ви можете отримати доступ item.idдо onItemClickметоду, як показано нижче:

    onItemClick = (event) => {
       console.log(e.target.getAttribute("item.id"));
    }
  3. Я згоден з вищезгаданим підходом для створення окремого компонента React для ListItem та List. Цей код створення виглядає добре, але якщо у вас є 1000 лі, тоді буде створено 1000 слухачів подій. Переконайтесь, що у вас не повинно бути багато слухачів подій.

    import React from "react";
    import ListItem from "./ListItem";
    export default class List extends React.Component {
    
        /**
        * This List react component is generic component which take props as list of items and also provide onlick
        * callback name handleItemClick
        * @param {String} item - item object passed to caller
        */
        handleItemClick = (item) => {
            if (this.props.onItemClick) {
                this.props.onItemClick(item);
            }
        }
    
        /**
        * render method will take list of items as a props and include ListItem component
        * @returns {string} - return the list of items
        */
        render() {
            return (
                <div>
                  {this.props.items.map(item =>
                      <ListItem key={item.id} item={item} onItemClick={this.handleItemClick}/>
                  )}
                </div>
            );
        }
    
    }
    
    
    import React from "react";
    
    export default class ListItem extends React.Component {
        /**
        * This List react component is generic component which take props as item and also provide onlick
        * callback name handleItemClick
        * @param {String} item - item object passed to caller
        */
        handleItemClick = () => {
            if (this.props.item && this.props.onItemClick) {
                this.props.onItemClick(this.props.item);
            }
        }
        /**
        * render method will take item as a props and print in li
        * @returns {string} - return the list of items
        */
        render() {
            return (
                <li key={this.props.item.id} onClick={this.handleItemClick}>{this.props.item.text}</li>
            );
        }
    }

1
Це не працює, коли дані, які вам потрібно передати, є об’єктом. Атрибут працюватиме лише з рядками. Також читання з дому через атрибут get, ймовірно, більш дорога операція.
SlimSim

2

Я додав код для передачі значення події onclick методу двома способами. 1. використовуючи метод прив’язки 2. за допомогою методу стрілки (=>). див. методи handlesort1 і handlesort

var HeaderRows  = React.createClass({
    getInitialState : function() {
      return ({
        defaultColumns : ["col1","col2","col2","col3","col4","col5" ],
        externalColumns : ["ecol1","ecol2","ecol2","ecol3","ecol4","ecol5" ],

      })
    },
    handleSort:  function(column,that) {
       console.log(column);
       alert(""+JSON.stringify(column));
    },
    handleSort1:  function(column) {
       console.log(column);
       alert(""+JSON.stringify(column));
    },
    render: function () {
        var that = this;
        return(
        <div>
            <div>Using bind method</div>
            {this.state.defaultColumns.map(function (column) {
                return (
                    <div value={column} style={{height : '40' }}onClick={that.handleSort.bind(that,column)} >{column}</div>
                );
            })}
            <div>Using Arrow method</div>

            {this.state.defaultColumns.map(function (column) {
                return (
                    <div value={column} style={{height : 40}} onClick={() => that.handleSort1(column)} >{column}</div>

                );
            })}
            {this.state.externalColumns.map(function (column) {
                // Multi dimension array - 0 is column name
                var externalColumnName = column;
                return (<div><span>{externalColumnName}</span></div>
                );
            })}

        </div>);
    }
});

2

Нижче наведено приклад, який передає значення події onClick.

Я використовував синтаксис es6. Пам'ятайте, що в класі компонент стрілка функція не прив'язується автоматично, тому явно прив'язує в конструкторі.

class HeaderRows extends React.Component {

    constructor(props) {
        super(props);
        this.handleSort = this.handleSort.bind(this);
    }

    handleSort(value) {
        console.log(value);
    }

    render() {
        return(
            <tr>
                {this.props.defaultColumns.map( (column, index) =>
                    <th value={ column } 
                        key={ index } 
                        onClick={ () => this.handleSort(event.target.value) }>
                        { column }
                    </th>
                )}

                {this.props.externalColumns.map((column, index)  =>
                    <th value ={ column[0] }
                        key={ index }>
                        {column[0]}
                    </th>
                )}
            </tr>
         );
    }
}

2

Я думаю, вам доведеться прив’язати метод до екземпляра класу React. Безпечніше використовувати конструктор, щоб зв’язати всі методи в React. У вашому випадку, коли ви передаєте параметр методу, перший параметр використовується для прив'язки контексту 'цього' методу, таким чином ви не можете отримати доступ до значення всередині методу.


2
1. You just have to use an arrow function in the Onclick event like this: 

<th value={column} onClick={() => that.handleSort(theValue)} >{column}</th>

2.Then bind this in the constructor method:
    this.handleSort = this.handleSort.bind(this);

3.And finally get the value in the function:
  handleSort(theValue){
     console.log(theValue);
}


2
class TableHeader extends Component {
  handleClick = (parameter,event) => {
console.log(parameter)
console.log(event)

  }

  render() {
    return (
      <button type="button" 
onClick={this.handleClick.bind(this,"dataOne")}>Send</button>
    );
  }
}

4
Хоча цей код може вирішити питання, у тому числі пояснення дійсно допомагає покращити якість вашої публікації. Пам’ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
Шрі

2

Виходьте з цього місця нізвідки, але я думаю, що .bindвдасться зробити свою справу. Знайдіть зразок коду нижче.

const handleClick = (data) => {
    console.log(data)
}

<button onClick={handleClick.bind(null, { title: 'mytitle', id: '12345' })}>Login</button>

1

Використання функції стрілки:

Ви повинні встановити етап-2:

npm встановити babel-попередньо встановлений етап-2:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value=0
        }
    }

    changeValue = (data) => (e) => {
        alert(data);  //10
        this.setState({ [value]: data })
    }

    render() {
        const data = 10;
        return (
            <div>
                <input type="button" onClick={this.changeValue(data)} />
            </div>
        );
    }
}
export default App; 

0

Є три способи впоратися з цим: -

  1. Прив’яжіть метод у конструкторі як: -

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
  2. Використовуйте функцію стрілки, створюючи її як: -

    handleSort = () => {
        // some text here
    }
  3. Третій спосіб такий: -

    <th value={column} onClick={() => that.handleSort} >{column}</th>

0

Ви можете використовувати свій код так:

<th value={column} onClick={(e) => that.handleSort(e, column)} >{column}</th>

Ось це для об'єкта події, якщо ви хочете використовувати методи подій, як preventDefault()у вашій функції ручки, або хочете отримати цільове значення або подібне ім'я e.target.name.


0

Я вважав рішення передачі парамуму як атрибуту тегу цілком розумним.

Однак він має обмеження:

  • Не працює належним чином, якщо в елементі списку є інші теги (таким чином, ціль event.target може відрізнятися від призначеного)
  • Парам може бути лише рядком. Вимагає серіалізації та десеріалізації.

Ось чому я придумав цю бібліотеку: react-event-param

Це:

  • Вирішує проблему дітей, шукаючи потрібний атрибут у батьків, коли це потрібно
  • Автоматично серіалізує і десеріалізує парам
  • Інкапсулює логіку налаштування та отримання. Не потрібно возитися з іменами парам

Приклад використання:

import { setEventParam, getEventParam } from "react-event-param";

class List extends Component {
  onItemClick = e => {
    const index = getEventParam(e.target);
    // Do something with index
  };

  render() {
    return (
      <ul>
        {this.props.items.map((itemText, index) => (
          <li
            key={index}
            {...setEventParam(index)}
            onClick={this.onItemClick}
          >
            {{ itemText }}
          </li>
        ))}
      </ul>
    );
  }
}

export default List;

0

Було багато міркувань щодо продуктивності, все у вакуумі.
Проблема з цими обробниками полягає в тому, що вам потрібно приправити їх, щоб включити аргумент, який ви не можете назвати у реквізиті.
Це означає, що компонент потребує обробника для кожного елемента, який можна натиснути. Погодимось, що для кількох кнопок це не проблема, правда?
Проблема виникає, коли ви обробляєте табличні дані з десятками стовпців і тисячами рядків. Там ви помічаєте вплив створення багатьох обробників.

Справа в тому, що мені потрібен лише один.
Я встановлюю обробник на рівні таблиці (або UL або OL ...), і коли відбувається натискання, я можу сказати, яка була клітинка, що натиснула, використовуючи дані, доступні з тих пір в об'єкті події:

nativeEvent.target.tagName
nativeEvent.target.parentElement.tagName 
nativeEvent.target.parentElement.rowIndex
nativeEvent.target.cellIndex
nativeEvent.target.textContent

Я використовую поля імен тегів, щоб перевірити, чи відбулося натискання у дійсному елементі, наприклад, ігнорувати кліки в THO та нижніх колонтитулах.
RowIndex та cellIndex вказують точне місце натиснутої комірки.
Textcontent - це текст кліку, що клацнув.

Таким чином, мені не потрібно передавати дані осередку обробнику, він може самообслуговувати їх.
Якщо мені потрібно більше даних, даних, які не підлягатимуть відображенню, я можу використовувати атрибут набору даних або приховані елементи.
За допомогою простої DOM-навігації все під рукою.
Це використовується в HTML з усіх часів, оскільки ПК було набагато простішим.


0

Є кілька способів передачі параметра в обробниках подій, деякі з них наведені нижче.

Ви можете використовувати функцію стрілки, щоб обернути обробник подій та передати параметри:

<button onClick={() => this.handleClick(id)} />

приклад вище є еквівалентом виклику, .bindабо ви можете явно зв’язати дзвінки.

<button onClick={this.handleClick.bind(this, id)} />

Крім цих двох підходів, ви також можете передавати аргументи функції, яка визначається як функція каррі.

handleClick = (id) => () => {
    console.log("Hello, your ticket number is", id)
};

<button onClick={this.handleClick(id)} />

-1

Використовуйте закриття , в результаті виходить чистий розчин:

<th onClick={this.handleSort(column)} >{column}</th>

Функція handleSort поверне функцію, у якій стовпець значення вже встановлений.

handleSort: function(value) { 
    return () => {
        console.log(value);
    }
}

Анонімна функція буде викликана з правильним значенням, коли користувач натисне на th.

Приклад: https://stackblitz.com/edit/react-pass-parameters-example


-2

Необхідна проста зміна:

Використовуйте <th value={column} onClick={that.handleSort} >{column}</th>

замість <th value={column} onClick={that.handleSort} >{column}</th>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.