React four ways to bind events form event controlled components and uncontrolled components

1 Introduction

The event handling of React elements is similar to DOM elements. But there is a little syntactic difference:

  • React event binding properties are namedCamel case, Instead of lowercase, for example, the native events are all lowercase onclick, and the events in React are hump onClick.
  • If the JSX syntax is requiredPass in a function as an event handler, Instead of a string (how DOM elements are written).
  • React events are not native events, but synthetic events.
  • Another difference in React is that you cannot prevent false behavior by returning false. You must explicitly use e.preventDefault ().

HTML is usually written as:

<button onclick="clickHandle()">提交</button>

<script>
function clickHandle(e){
	e.preventDefault();	//阻止默认事件
	//或者使用如下的写法
	return false;
}
</script>

The wording in React is:

<button onClick={clickHandle}>提交</button>

<script>
function clickHandle(e){
	e.preventDefault();	//阻止默认事件,不能使用return false
}
</script>

2. Several ways for React to bind events

  • When using ES6 class syntax to define a component, the event handler becomes a method of the class.
  • You must be careful about this in the JSX callback function. The methods of the class will not bind this by default. If you forget to bind this.handleClick and pass it to onClick, the value of this will be undefined when you call this function.
  • Normally, if you don't add () after the method, for example onClick = {this.handleClick}, you should bind this to this method.

2.1 Method one

Use the arrow function in the callback function, and directly write the inline arrow function in render () (not recommended) . The problem with this method is that a different callback function is created each time render () is executed. In most cases, this is no problem. However, if this callback function is passed as a property value to low-level components, these components may be re-rendered additionally.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Box extends Component {
  handleClick(e,val){
  	console.log(e,val);
  }
  render() {
    return (
      <button onClick={(e)=>this.handleClick(e,'aa')}>添加</button>
    );
  }
}

ReactDOM.render(
  <Box />,
  document.getElementById('root')
);

2.2 Method two

In the render () method, use bind to bind this (not recommended) . Define a non-arrow function directly in the component, and then use it directly in render. onClick={this.handleClick.bind(this)}The disadvantage of this method is that every time you use bind to bind this, the code will be redundant:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Box extends Component {
	handleClick(val,e) {	//事件对象e要放在最后
		console.log(val,e);
	}
	render() {
		return (
			<button onClick={this.handleClick.bind(this, 'aa')}>添加</button>
		);
	}
}

ReactDOM.render(
  <Box />,
  document.getElementById('root')
);

2.3 Method Three

Use the property initializer to correctly bind the callback function (recommended) , and use the arrow function to define a method in the component. The disadvantage of this method is that you cannot customize the parameter:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Box extends Component {
	handleClick =(e)=>{
		console.log(e);
	}
	render() {
		return (
			<button onClick={this.handleClick}>添加</button>
		);
	}
}

ReactDOM.render(
  <Box />,
  document.getElementById('root')
);

2.4 Method 4

Define a method of a non-arrow function directly in the component, and then bind (this) (recommended) in the constructor. The advantage of this method is that the performance is better. No matter how many times render () is executed, it eventually points to the same reference. The disadvantage of this method is that you can't customize the parameters.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Box extends Component {
	constructor(){
		super();
		this.myhandleClick = this.handleClick.bind(this);
	}
	handleClick(e){
		console.log(e);
	}
	render() {
		return (
			<button onClick={this.myhandleClick}>添加</button>
		);
	}
}

ReactDOM.render(
  <Box />,
  document.getElementById('root')
);

3. React event parameter

Like ordinary browsers, the event handleClick will be automatically passed into an event object, which contains basically the same methods and properties as the ordinary browser event object. React difference is that the eventobjects are not provided by the browser, but its own internal constructed. It also has event.stopPropagation, event.preventDefaultsuch a conventional method.

Pass additional parameters for the event handler, usually using the two methods (2.1, 2.2) above, namely:

<button onClick={(e)=>this.handleClick(e, 'aa')}>添加</button>
<button onClick={this.handleClick.bind(this, 'aa')}>添加</button>

It is worth noting that by passing parameters to the listener function through the bind method, the listener function defined in the class component, the event object e should be arranged after the passed parameter.

3.1 Modifying parameters in subcomponents

Modify the parameters passed by the parent component in the child component. The more recommended method is to define the method in the parent component, call the parent component's method propsin the child component, pass it to the child component, and then this.props.methodcall it in the child component . See the example below:

Code in subcomponents:

class Button extends Component {
  handleClick(){
  	//执行DOM元素的 change属性
    this.props.change();
  }
  render() {
    return (
     <button onClick={()=>this.handleClick()}>
       {this.props.children}
     </button>
    );
  }
}

Code in the parent component:

class Counter extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    }
  }
  handleChange(type) {
    this.setState((preState, props) => {
          count: preState.count + 1
      } 
    }, () => { })
  }

  render() {
    return (
      <div >
        <Button change={() => this.handleChange()}>-</Button>
      </div>
    );
  }
}

4. Form events

HTML form elements are different from other DOM elements in React because form elements retain some internal state from birth.

In HTML, form elements such as <input>, <textarea>, and <select> maintain their own state and are updated based on user input. But in React, the variable state is usually saved in the state attribute of the component, and can only be updated with the setState () method.

4.1 Controlled components

forFor controlled components, the input value is always driven by React's state. The React component that renders the form also controls what happens to the form during user input. Form input elements controlled by React in this way are called "controlled components".

For example, if we want all lowercase letters entered by the user to be converted to uppercase letters, we can write the form as a controlled component:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Form extends Component {
  constructor() {
    super();
    this.state = {name: ""}
  }
  handleChange(event) {
    this.setState({
      name: event.target.value.toUpperCase() //	将输入的字母转成大写
    })
  }
  render() {
    return (
      <div>名称:<input type="text" value={this.state.name} onChange={this.handleChange.bind(this)} /></div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);

Since the value attribute is set on the form element, soThe displayed value will always be this.state.value, Which makes React's state the only data source. Use the onChange event to monitor input changes and modify the state. Due to handlechangeThe state of React is executed and updated every time a key is pressed, Convert the letters to uppercase, so the displayed value will be updated as the user enters it.

4.2 Multiple input elements

  • When there are multiple input elements to be processed, you can passAdd a name attribute to each elementTo let handler based on event.target.namethe value of the choice of what to do.
  • In React, <textarea> uses the value attribute instead. In this way, the form using <textarea> is very similar to the form using single line input.
  • In React, the Select drop-down menu does not use the selected attribute, but the value attribute is used to indicate the selected item on the root select label. When Select is multiple selection, the corresponding state should be an array.
  • Note: The value of <input type = “file”> is read-only, so it is an uncontrolled component in React.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Form extends Component {
  constructor() {
    super();
    this.state = {
      name: "",
      desc: "",
      city: [1,2]
    }
  }
  handleChange(event) {
    if(event.target.name==='city'){
      this.state.city.push(event.target.value);
      this.setState({})
      return;
    }
    this.setState({
      [event.target.name]: event.target.value
    })
  }
  render() {
    return (
      <div>
        名称:<input type="text" value={this.state.name} name="name" onChange={this.handleChange.bind(this)} />
        描述:<textarea name="desc" value={this.state.desc} onChange={this.handleChange.bind(this)}></textarea>
        城市:<select name="city" multiple 
        value={this.state.city}
        onChange={this.handleChange.bind(this)}>
          <option value="1">北京</option>
          <option value="2">上海</option>
          <option value="3">天津</option>
        </select>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);

Overall, this makes tags like <input type = “text”>, <textarea> and <select> very similar—they all accept a value attribute, which you can use to implement controlled components.

4.3 Application scenarios of controlled components

Application scenarios of controlled components: You can monitor user input and change the data input by the user. For example, the above will convert the input letters to uppercase, determine whether the user input is empty, etc.

If you want to find a complete solution that includes validation, tracking access fields, and processing form submissions, using Formik is a good choice. However, it is also based on controlled components and managing state

Sometimes using controlled components can be cumbersome, because you need to write event handlers for every way the data changes, and pass all the input state through a React component. In these cases, you may want to use uncontrolled components, which is another way to implement input forms.

4.4 Uncontrolled components

Uncontrolled component, the value displayed by the component is completely not controlled by the state. Use the ref attribute to bind to any component output by render (). Obtain the bound DOM element through the ref attribute, similar to the use of ref in vue.

How to use ref:

When the ref attribute value is static content:
1. Bind a ref attribute to the return value of render;
2. Get the bound DOM element through this.refs;

When the ref attribute value is state:
1. Use import to import react.createRef;
2. Use state as the attribute value of ref and bind it to the return value of render;
3. Obtain the bound DOM element through state.current;

import React, { Component,createRef } from 'react';
import ReactDOM from 'react-dom';

class Form extends Component {
  constructor() {
    super();
    this.title = createRef()
  }
  handleSubmit = () => {
    console.log(this.title.current.value)
    console.log(this.refs.myInput.value)
  }
  render() {
    return (
      <div>
        <input type="text" ref={this.title}/>
        <input type="text" ref='myInput'/>
        <button onClick={this.handleSubmit}>提交</button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);
Published 139 original articles · praised 51 · 30,000+ views

Guess you like

Origin blog.csdn.net/Charissa2017/article/details/105642021