React и событие onClick
Есть простейший компонент - форма. В нём инпут и кнопка. Подскажите, почему, если на кнопку, повесить событие onClick и записать так: onClick = {() => console.log(value)}, то код работает (для меня) ожидаемо, т.е. я что-то вписываю в инпут, жму на кнопку и вижу в консоли, содержимое инпута.
Но, если, записать вот так: onClick = {console.log(value)}, то данные выводятся в консоль, сразу же, после изменений в инпуте, не дожидаясь клика по кнопке.
Другими словами, в чем разница, между записями onClick = {() => console.log(value)} и onClick = {console.log(value)}, на примере моего компонента?
import { Component } from "react";
export default class ItemAdder extends Component {
state = {
value: ""
};
onInputChange = (event) => {
this.setState({
value: event.target.value
});
};
onSubmit = (e) => {
e.preventDefault();
};
render() {
let {value} = this.state;
return (
<form className="formAdd" onSubmit={this.onSubmit}>
<input
type="text"
value={this.state.value}
placeholder="Add ToDo item here"
onChange={this.onInputChange}
/>
<button className="add"
onClick = {console.log(value)}>+</button>
</form>
);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Ответы (2 шт):
() => console.log(value) - это функция. Если ее передать в onClick, то она будет вызвана, когда произойдет событие click.
console.log(value) - это вызов функции, который возвращает undefined. Если его передать в onClick, то это все равно что передать onClick={undefined} - то есть на событие ничего вызываться не будет. А вывод в консоль происходит при вызове render(), который происходит каждый раз при изменении инпута (= изменение стейта).
При вот такой записи
onClick = {() => console.log(value)}
вы инициализируете функцию (callback), которая будет исполняться только при наступлении события event'a. Ничего такого в этом нет и будет работать, как и должно, но есть одно НО: при каждом рендере будет создаваться новая функция. Это надо учитывать и вот такой вид не то, чтобы правильней, но позволяет избегать некоторых ошибок
clickMe = () =>{
console.log(this.state);
}
....
render() {
...
<button className="add"
onClick = {this.clickMe}>+</button>
...
}
или
clickMe(){
console.log(this.state);
}
....
render() {
...
<button className="add"
onClick = {() = > this.clickMe()}>+</button>
...
}
В противном случае запись
onClick = {console.log(value)}
вы буквально говорите -> "При рендере в слушатель onClick передать это - вывести в консоль value". А должно быть -> "При рендере определить/передать функцию (callback) которая исполняется при наступлении события"
UPD здесь наверное необходимо погружение в то, что называется callback. Здесь можно почитать. А вот насколько глубоко вы собрались погружаться, я не знаю. Весь код открыт, можете проследить как определен onClick.
Пример:
Определение button
button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>;
Какие пропсы
type DetailedHTMLProps<E extends HTMLAttributes<T>, T> = ClassAttributes<T> & E;
Смотрим от что наследуем HTMLAttributes
interface DOMAttributes<T> {
children?: ReactNode | undefined;
dangerouslySetInnerHTML?: {
__html: string;
} | undefined;
......
// MouseEvents
onAuxClick?: MouseEventHandler<T> | undefined;
onAuxClickCapture?: MouseEventHandler<T> | undefined;
onClick?: MouseEventHandler<T> | undefined;
и так далее