Example: get the distance from the button element to the top of the page
ref is written on html elements
import React,{Component,Fragment} from 'react'; import Child from './Child'; class Counter extends Component{ constructor(props){ super(props); this.addCount=this.addCount.bind(this); this.state={ counter:1 } } addCount(){ console.log(this.button); console.log(this.button.clientTop); this.setState({ counter:this.state.counter+1 }) } render(){ return( <Fragment> <button onClick={this.addCount} ref={button=>this.button=button}>click</button> <Child num={this.state.counter}/> </Fragment> ) } } export default Counter;
ref is written on the component. It gets the instance of the component
import React,{Component,Fragment} from 'react'; import Child from './Child'; class Counter extends Component{ constructor(props){ super(props); this.addCount=this.addCount.bind(this); this.state={ counter:1 } } addCount(){ console.log(this.child); this.setState({ counter:this.state.counter+1 }) } render(){ return( <Fragment> <button onClick={this.addCount}>click</button> <Child num={this.state.counter} ref={child=>this.child=child}/> </Fragment> ) } } export default Counter;
Conclusion: ref is written on the html tag, and the DOM node is obtained
ref is written on the component tag to get the JS instance of the component
setState asynchronous, instance:
import React,{Component,Fragment} from 'react'; class Counter extends Component{ constructor(props){ super(props); this.addCount=this.addCount.bind(this); this.state={ counter:1 } } addCount(){ console.log(this.div.innerHTML); this.setState({ counter:this.state.counter+1 }) console.log(this.div.innerHTML); } render(){ return( <Fragment> <button onClick={this.addCount}>click</button> <div ref={div=>this.div=div}>{this.state.counter}</div> </Fragment> ) } } export default Counter;
You can see that the output of both times is 1, which proves that the setState operation is performed asynchronously
resolvent:
import React,{Component,Fragment} from 'react'; class Counter extends Component{ constructor(props){ super(props); this.addCount=this.addCount.bind(this); this.state={ counter:1 } } addCount(){ console.log(this.div.innerHTML); this.setState(()=>{ return{ counter:this.state.counter+1 } },()=>{ console.log(this.div.innerHTML); }) } render(){ return( <Fragment> <button onClick={this.addCount}>click</button> <div ref={div=>this.div=div}>{this.state.counter}</div> </Fragment> ) } } export default Counter;
In this way, the second print will be executed after setState is executed
Result: