9

React JS: невозможно передать значение в метод через onClick

11

Проблема с передачей значения в обработчик onClick в React.js

Я хочу получить свойства значения события 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) {
          // Многомерный массив - 0 это имя колонки
          var externalColumnName = column[0];
          return <th>{externalColumnName}</th>;
        })}
      </tr>
    );
  }
});

Как мне передать значение в событие onClick в React.js?

5 ответ(ов)

1

Сейчас, с появлением 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);
}

Однако предпочтительнее использовать стрелочные функции для вызова методов, чтобы избежать необходимости в дополнительном связывании.

0

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

  1. Использование атрибутов: Вы используете атрибут data-column для хранения информации о колонне, что является хорошей практикой. Это позволяет сохранить чистоту кода и удобно передавать данные.

  2. Обработчик событий: Ваш метод handleSort получает объект события и использует его для извлечения значения из атрибута data-column. Это тоже нормально. Однако, чтобы сделать код более чистым и уменьшить вероятность ошибок, вы можете прямо передать имя колонки в метод handleSort.

    Например, можно сделать следующим образом:

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

    И тогда ваш метод будет выглядеть так:

    handleSort(column) {
        this.sortOn(column);
    }
    
  3. Избегание getAttribute: Передавая колонну напрямую, вы избавляетесь от необходимости вызывать getAttribute, что упрощает код и делает его более читабельным.

В остальном, ваш код выглядит корректно. Убедитесь, что sortOn умеет обрабатывать данные правильно, чтобы сортировка работала как ожидается. Надеюсь, это поможет!

0

Решение с использованием React Hooks 2022

const arr = [
  { id: 1, txt: 'One' },
  { id: 2, txt: 'Two' },
  { id: 3, txt: 'Three' },
]

const App = () => {
  const handleClick = useCallback(
    (id) => () => {
      console.log("ID: ", id)
    },
    [],
  )

  return (
    <div>
      {arr.map((item) => (
        <button onClick={handleClick(item.id)}>{item.txt}</button>
      ))}
    </div>
  )
}

Вы можете передать функцию в возвращаемое значение useCallback, а затем вызвать вашу функцию как обычно, передавая ей параметры в процессе рендеринга. Работает замечательно! Просто убедитесь, что вы правильно установили массив зависимостей для useCallback.

Лучшее решение с React >= 16

Чистейший способ вызвать функции с несколькими параметрами в onClick, onChange и т. д. без использования инлайновых функций — это использование пользовательского атрибута data, доступного в версиях React 16 и выше.

const App = () => {
  const onClick = (e) => {
    const value1 = e.currentTarget.getAttribute("data-value1")
    const value2 = e.currentTarget.getAttribute("data-value2")
    const value3 = e.currentTarget.getAttribute("data-value3")
    console.log("Values1", value1)
    console.log("Values2", value2)
    console.log("Values3", value3)
  }
  return (
    <button onClick={onClick} data-value1="a" data-value2="b" data-value3="c" />
  )
}

Приведённый выше пример предназначен для функционального компонента, но реализация довольно похожа и в классовых компонентах.

Этот подход не приводит к лишним перерисовкам, поскольку вы не используете инлайновые функции, и вам не нужно беспокоиться о связывании с this.

Это позволяет вам передавать столько значений, сколько вам нужно для использования в вашей функции.

Если вы передаёте значения в качестве пропсов своим детям, чтобы использовать их в onClick дочернего компонента, вы можете использовать этот подход и там, не создавая обёрточную функцию.

Работает и с массивами объектов, когда вам нужно передать id из объекта в onClick, как показано ниже.

const App = () => {
  const [arrState, setArrState] = useState(arr)

  const deleteContent = (e) => {
    const id = e.currentTarget.getAttribute("data-id")
    const tempArr = [...arrState]
    const filteredArr = tempArr.filter((item) => item.id !== id)
    setArrState(filteredArr)
  }

  return (
    <div>
      {arrState.map((item) => (
        <React.Fragment key={item.id}>
          <p>{item.content}</p>
          <button onClick={deleteContent} data-id={item.id}>
            Удалить
          </button>
        </React.Fragment>
      ))}
    </div>
  )
}

Надеюсь, это поможет вам с вашим вопросом! Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

0

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

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

  handleClick(event) {
    const { param } = event.target.dataset;
    console.log(param);
    // делайте то, что вам нужно с параметром
  }

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

Обновление

Если вам нужно передавать объекты в качестве параметров, вы можете использовать JSON.stringify(object), чтобы преобразовать его в строку и добавить в data-атрибут.

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

Надеюсь, это поможет вам в вашей задаче!

0

Просто создайте функцию, например, так:

function методИмя(параметры) {
  // то, что вы хотите сделать
}

И вызовите ее в нужном месте:

<Icon onClick={() => { методИмя(параметрыЧтобыПередать); }} />
Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь