React - onChange don't work when attach without parentheses?

Viewed 52

I have seen something weird when working with onChange in React.

The basic flow is to listen for changes of this.props.tableBody and trigger autoscroll to the table bottom. The tableBody is a list of items.

I use react class component and have bound the function already.

class ProgressTable extends Component {
    constructor(props) {
        super(props);
        this.onTableChangeHandler = this.onTableChangeHandler.bind(this);
    }

    onTableChangeHandler() {
        console.log("hi from onTableChangeHandler");
    }

    render() {
        return (
            <div className="table-body-container" onChange={this.onTableChangeHandler}> // not work
                {this.props.tableBody}
            </div>
        );
    }
}

As usual, the code should be fine.

But something weird happened here. The onChange, which should invoke onTableChangeHandler function now doesn't.

I have tried to figure out what is happening here and found that if I add () to the onChange attached function like this, the code is working and listen for the changes correctly except for the first redundant call when component render.

<div className="table-body-container" onChange={this.onTableChangeHandler()}> // work like usual
    {this.props.tableBody}
</div>

Furthermore, I have tried this and it also works.

<div className="table-body-container" onChange={console.log("hi")}> // "hi"
    {this.props.tableBody}
</div>

Can you show me what and why this happened?

1 Answers

onChange event handler is used for elements like input or select. When you type in an input element it invokes the onChange but div's don't "change" as such so nothing will happen.

If you are looking for something to happen when the div is clicked you need to use onClick handler instead.

What you are doing here (onChange={this.onTableChangeHandler()}) is essentially manually calling your function immediately when the component renders (and on every subsequent render) and that's why it looks like it's working even when you use it in a handler that shouldn't really work when used on divs, but in reality this is just bad practice.

Related