[React]: Handling Events
React
10/04/2019
Handling events in functional component (w/ hooks)
JSX
const Person = ({ name, age }) => {  return <p>{`Name: ${name}`}</p>}
const App = () => {  const [persons, setPersons] = React.useState([{ name: "A" }, { name: "B" }])
  const changeNames = () => {    setPersons([{ name: "C" }, { name: "D" }])  }
  return (    <div>      {persons.map(person => {        return <Person name={person.name} age={person.age} />      })}      <button onClick={changeNames}>Click</button>    </div>  )}
ReactDOM.render(<App />, document.getElementById("root"))Use bind() when passing an argument
JSX
const Person = ({ name, age }) => {  return <p>{`Name: ${name}`}</p>}
const App = () => {  const [persons, setPersons] = React.useState([{ name: "A" }, { name: "B" }])
  const changeNames = newName => {    setPersons([{ name: newName }, { name: newName }])  }
  return (    <div>      {persons.map(person => {        return <Person name={person.name} age={person.age} />      })}      <button onClick={changeNames.bind(this, "Z")}>Click</button>    </div>  )}
ReactDOM.render(<App />, document.getElementById("root"))Handling events in class component
App.js
JSX
const Person = ({ name }) => {  return <p>{`Name: ${name}`}</p>}
class App extends React.Component {  constructor(props) {    super(props)    this.state = {      persons: [{ name: "A" }, { name: "B" }],    }    // bind(this) is necessary to make `this` work in the callback    this.handleChangeNames = this.handleChangeNames.bind(this)  }
  handleChangeNames(e) {        e.preventDefault()     this.setState({ persons: [{ name: "C" }, { name: "D" }] })   } 
  render() {    return (      <div>        {this.state.persons.map(person => {          return <Person name={person.name} age={person.age} />        })}        <button onClick={this.handleChangeNames}>Click</button>      </div>    )  }}
ReactDOM.render(<App />, document.getElementById("root"))
eis a synthetic event which is passed in as argument.e.preventDefault()stops the default action of a selected element
Using arrow function(ES6) without bind()
App.js
JSX
const Person = ({ name }) => {  return <p>{`Name: ${name}`}</p>}
class App extends React.Component {  state = {    persons: [{ name: "A" }, { name: "B" }],  }
  // Ensures `this` is bound within handleChangeNames  handleChangeNames = e => {    e.preventDefault()    this.setState({ persons: [{ name: "C" }, { name: "D" }] })  } 
  render() {    return (      <div>        {this.state.persons.map(person => {          return <Person name={person.name} age={person.age} />        })}        <button onClick={this.handleChangeNames}>Click</button>      </div>    )  }}
ReactDOM.render(<App />, document.getElementById("root"))Passing arguments
When passing arguments, you'd still have to bind the function. i.e.
JSX
const Person = ({ name }) => {  return <p>{`Name: ${name}`}</p>}
class App extends React.Component {  state = {    persons: [{ name: "A" }, { name: "B" }],  }
  handleChangeNames = newName => {    this.setState({ persons: [{ name: newName }, { name: "D" }] })  }
  render() {    return (      <div>        {this.state.persons.map(person => {          return <Person name={person.name} age={person.age} />        })}        <button onClick={this.handleChangeNames.bind(this, "Z")}>Click</button>        =================== OR ===================        <button onClick={() => this.handleChangeNames("Z")}>Click</button>      </div>    )  }}
ReactDOM.render(<App />, document.getElementById("root"))Arrow functions vs bind()
When passing arguments, below two lines are equivalent. arrow functions and Function.prototype.bind both will work; however, be aware that arrow function callback gets created each time App.js renders. This may result in inefficiency when callback is passed as prop to child components that can perform re-rendering. Thus, bind() is recommended over arrow functions.
JSX
<button onClick={this.handleChangeNames.bind(this, "Z")}>Click</button><button onClick={() => this.handleChangeNames.("Z")}>Click</button>