React JS: невозможно передать значение в метод через onClick
Проблема с передачей значения в обработчик 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 ответ(ов)
Сейчас, с появлением 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);
}
Однако предпочтительнее использовать стрелочные функции для вызова методов, чтобы избежать необходимости в дополнительном связывании.
Ваш подход выглядит вполне разумно, но есть несколько моментов, которые стоит обсудить для повышения качества кода.
Использование атрибутов: Вы используете атрибут
data-column
для хранения информации о колонне, что является хорошей практикой. Это позволяет сохранить чистоту кода и удобно передавать данные.Обработчик событий: Ваш метод
handleSort
получает объект события и использует его для извлечения значения из атрибутаdata-column
. Это тоже нормально. Однако, чтобы сделать код более чистым и уменьшить вероятность ошибок, вы можете прямо передать имя колонки в методhandleSort
.Например, можно сделать следующим образом:
return ( <th onClick={() => this.handleSort(column)}>{column}</th> );
И тогда ваш метод будет выглядеть так:
handleSort(column) { this.sortOn(column); }
Избегание
getAttribute
: Передавая колонну напрямую, вы избавляетесь от необходимости вызыватьgetAttribute
, что упрощает код и делает его более читабельным.
В остальном, ваш код выглядит корректно. Убедитесь, что sortOn
умеет обрабатывать данные правильно, чтобы сортировка работала как ожидается. Надеюсь, это поможет!
Решение с использованием 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>
)
}
Надеюсь, это поможет вам с вашим вопросом! Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.
Этот пример может немного отличаться от вашего, но я могу вас заверить, что это лучшее решение для вашей проблемы. Я искал решение в течение нескольких дней, которое не имело бы проблем с производительностью, и наконец пришел к этому.
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>
);
Надеюсь, это поможет вам в вашей задаче!
Просто создайте функцию, например, так:
function методИмя(параметры) {
// то, что вы хотите сделать
}
И вызовите ее в нужном месте:
<Icon onClick={() => { методИмя(параметрыЧтобыПередать); }} />
Как программно выполнять навигацию с помощью React Router?
Как условно добавлять атрибуты к компонентам React?
Как установить фокус на поле ввода после рендеринга?
Метод set в useState не отражает изменения немедленно
В чем разница между React Native и React?