1. Export life cycle
Requirements: Define components to implement the following functions
- Make the specified text do show/hide gradient animation
- From being fully visible to completely disappearing, it takes 2S
- Click the “Dead” button to uninstall the component from the interface
<!-- Prepare a "container" --> <div id="test"></div> \t <script type="text/babel"> //Create component //Lifecycle callback function <=> lifecycle hook function <=> lifecycle function <=> lifecycle hook class Life extends React. Component{<!-- --> state = {<!-- -->opacity:1} death = ()=>{<!-- --> //Uninstall the component ReactDOM.unmountComponentAtNode(document.getElementById('test')) } //The component is hung componentDidMount(){<!-- --> console.log('componentDidMount'); this.timer = setInterval(() => {<!-- --> //Get the original state let {<!-- -->opacity} = this.state //decrease by 0.1 opacity -= 0.1 if(opacity <= 0) opacity = 1 // set the new transparency this.setState({<!-- -->opacity}) }, 200); } //The component will be unmounted componentWillUnmount(){<!-- --> //clear timer clearInterval(this. timer) } //After initial rendering and state update render(){<!-- --> console.log('render'); return( <div> <h2 style={<!-- -->{<!-- -->opacity:this.state.opacity}}>What if you can't learn React? </h2> <button onClick={<!-- -->this.death}>Not alive</button> </div> ) } } // render component ReactDOM.render(<Life/>,document.getElementById('test')) </script>
2. Understanding of life cycle
- Lifecycle callback function <=> lifecycle hook function <=> lifecycle function <=> lifecycle hook
1. A component will go through some specific stages from creation to death. 2. React components contain a series of hook functions (life cycle callback functions), which will be called at specific moments. 3. When we define a component, we will do specific work in a specific life cycle callback function
3. Life cycle (old)
1. Life cycle flowchart (old)
2. Phases of the lifecycle
Initialization phase: Triggered by ReactDOM.render()-first render
1. constructor() 2. componentWillMount() 3. render() 4. componentDidMount() ===> commonly used Generally, do some initialization in this hook, such as: start timer, send network request, subscribe message
Update phase: triggered by this.setSate() inside the component or the render of the parent component
1. shouldComponentUpdate() 2. componentWillUpdate() 3.render() =====> must use one 4. componentDidUpdate()
Unmount component: Triggered by ReactDOM.unmountComponentAtNode()
componentWillUnmount() =====> Commonly used Generally, do some final things in this hook, such as closing the timer and unsubscribing from the message
3. Life cycle validation
<!-- Prepare a "container" --> <div id="test"></div> \t <script type="text/babel"> //Create component class Count extends React. Component{<!-- --> //constructor constructor(props){<!-- --> console.log('Count---constructor'); super(props) //Initialize state this.state = {<!-- -->count:0} } //callback for plus 1 button add = ()=>{<!-- --> //Get the original state const {<!-- -->count} = this.state \t\t\t\t//update status this.setState({<!-- -->count:count + 1}) } //Callback for uninstall component button death = ()=>{<!-- --> ReactDOM.unmountComponentAtNode(document.getElementById('test')) } //Callback for force update button force = ()=>{<!-- --> this. forceUpdate() } //The hook that the component will mount componentWillMount(){<!-- --> console.log('Count---componentWillMount'); } //The hook for the component to be mounted componentDidMount(){<!-- --> console.log('Count---componentDidMount'); } //The hook for the component to be uninstalled componentWillUnmount(){<!-- --> console.log('Count---componentWillUnmount'); } //The "valve" that controls component updates shouldComponentUpdate(){<!-- --> console.log('Count---shouldComponentUpdate'); return true } //The hook that the component will update componentWillUpdate(){<!-- --> console.log('Count---componentWillUpdate'); } //The hook for the component to be updated componentDidUpdate(){<!-- --> console.log('Count---componentDidUpdate'); } render(){<!-- --> console.log('Count---render'); const {<!-- -->count} = this.state return( <div> <h2>The current sum is: {<!-- -->count}</h2> <button onClick={<!-- -->this.add}>click me + 1</button> <button onClick={<!-- -->this.death}>Uninstall component</button> <button onClick={<!-- -->this.force}>Do not change the data in any state, force to update it</button> </div> ) } } ReactDOM.render(<Count/>,document.getElementById('test')) </script>
The render process of the parent component
<!-- Prepare a "container" --> <div id="test"></div> <script type="text/babel"> //Parent component A class A extends React. Component{<!-- --> //Initialize state state = {<!-- -->carName:'Benz'} changeCar = ()=>{<!-- --> this.setState({<!-- -->carName:'Alto'}) } render(){<!-- --> return( <div> <div>I am A component</div> <button onClick={<!-- -->this.changeCar}>Change car</button> <B carName={<!-- -->this.state.carName}/> </div> ) } } \t\t //Subcomponent B class B extends React. Component{<!-- --> // the hook that the component will receive new props componentWillReceiveProps(props){<!-- --> console.log('B---componentWillReceiveProps',props); } //The "valve" that controls component updates shouldComponentUpdate(){<!-- --> console.log('B---shouldComponentUpdate'); return true } //The hook that the component will update componentWillUpdate(){<!-- --> console.log('B---componentWillUpdate'); } //The hook for the component to be updated componentDidUpdate(){<!-- --> console.log('B---componentDidUpdate'); } render(){<!-- --> console.log('B---render'); return( <div>I am component B, and the received car is: {<!-- -->this.props.carName}</div> ) } } \t\t // render component ReactDOM.render(<A/>,document.getElementById('test')) </script>
4. Life cycle (new)
1. Life cycle flowchart (new)
2. Phases of the lifecycle
Initialization phase: Triggered by ReactDOM.render()-first render
1. constructor() 2. getDerivedStateFromProps 3. render() 4. componentDidMount() =====> Commonly used. Generally, do some initialization in this hook, such as: start timer, send network request, subscribe message
Update phase: triggered by this.setSate() inside the component or re-render of the parent component
1. getDerivedStateFromProps 2. shouldComponentUpdate() 3. render() 4. getSnapshotBeforeUpdate 5. componentDidUpdate()
Unmount component: Triggered by ReactDOM.unmountComponentAtNode()
componentWillUnmount() =====> Commonly used Generally, do some final things in this hook, such as closing the timer and unsubscribing from the message
3. Life cycle validation
<!-- Prepare a "container" --> <div id="test"></div> <script type="text/babel"> //Create component class Count extends React. Component{<!-- --> //constructor constructor(props){<!-- --> console.log('Count---constructor'); super(props) //Initialize state this.state = {<!-- -->count:0} } //callback for plus 1 button add = ()=>{<!-- --> //Get the original state const {<!-- -->count} = this.state \t\t\t\t//update status this.setState({<!-- -->count:count + 1}) } //Callback for uninstall component button death = ()=>{<!-- --> ReactDOM.unmountComponentAtNode(document.getElementById('test')) } //Callback for force update button force = ()=>{<!-- --> this. forceUpdate() } \t\t\t //If the value of state depends on props at any time, you can use getDerivedStateFromProps static getDerivedStateFromProps(props,state){<!-- --> console.log('getDerivedStateFromProps',props,state); return null } // Get a snapshot before updating getSnapshotBeforeUpdate(){<!-- --> console.log('getSnapshotBeforeUpdate'); return 'atguigu' } //The hook for the component to be mounted componentDidMount(){<!-- --> console.log('Count---componentDidMount'); } //The hook for the component to be uninstalled componentWillUnmount(){<!-- --> console.log('Count---componentWillUnmount'); } //The "valve" that controls component updates shouldComponentUpdate(){<!-- --> console.log('Count---shouldComponentUpdate'); return true } //The hook for the component to be updated componentDidUpdate(preProps, preState, snapshotValue){<!-- --> console.log('Count---componentDidUpdate', preProps, preState, snapshotValue); } \t\t\t render(){<!-- --> console.log('Count---render'); const {<!-- -->count} = this.state return( <div> <h2>The current sum is: {<!-- -->count}</h2> <button onClick={<!-- -->this.add}>click me + 1</button> <button onClick={<!-- -->this.death}>Uninstall component</button> <button onClick={<!-- -->this.force}>Do not change the data in any state, force to update it</button> </div> ) } } \t\t // render component ReactDOM.render(<Count count={<!-- -->199}/>,document.getElementById('test')) </script>
4. Usage scenarios of getSnapshotBeforeUpdate
<style> .list{<!-- --> width: 400px; height: 150px; background-color: skyblue; overflow: auto; margin: 0 auto; } .news{<!-- --> height: 30px; } </style>
<!-- Prepare a "container" --> <div id="test"></div> \t <script type="text/babel"> class NewsList extends React. Component{<!-- --> state = {<!-- -->newsArr:[]} componentDidMount(){<!-- --> setInterval(() => {<!-- --> //Get the original state const {<!-- -->newsArr} = this.state //Simulate a news const news = 'news' + (newsArr.length + 1) \t\t\t\t\t//update status this.setState({<!-- -->newsArr:[news,...newsArr]}) }, 1000); } getSnapshotBeforeUpdate(){<!-- --> return this.refs.list.scrollHeight } componentDidUpdate(preProps, preState, height){<!-- --> this.refs.list.scrollTop + = this.refs.list.scrollHeight - height } render(){<!-- --> return( <div className="list" ref="list"> {<!-- --> this.state.newsArr.map((n,index)=>{<!-- --> return <div key={<!-- -->index} className="news">{<!-- -->n}</div> }) } </div> ) } } ReactDOM.render(<NewsList/>,document.getElementById('test')) </script>
5. Important hooks
1. render: call to initialize rendering or update rendering 2. componentDidMount: open monitoring, send ajax request 3. componentWillUnmount: Do some finishing work, such as: clean up the timer
6. The hook that is about to be discarded
1. componentWillMount 2. componentWillReceiveProps 3. componentWillUpdate There will be a warning when using it now. The next major version needs to be prefixed with UNSAFE_ before it can be used. It may be completely abandoned in the future. It is not recommended to use
5. DOM Diffing Algorithm
1. Verify Diffing algorithm
<!-- Prepare a "container" --> <div id="test"></div> \t <script type="text/babel"> class Time extends React. Component {<!-- --> state = {<!-- -->date: new Date()} componentDidMount () {<!-- --> setInterval(() => {<!-- --> this.setState({<!-- --> date: new Date() }) }, 1000) } render () {<!-- --> return ( <div> <h1>hello</h1> <input type="text"/> <br/> <span> Now it is: {<!-- -->this.state.date.toTimeString()} <input type="text"/> </span> </div> ) } } ReactDOM.render(<Time/>,document.getElementById('test')) </script>
2. The function of key
Classic interview questions
Classic interview questions: 1). What is the function of the key in react/vue? (What is the internal principle of the key?) 2). Why is it better not to use index for the key when traversing the list? 1. The role of key in virtual DOM: 1). Simply put: the key is the identifier of the virtual DOM object, and the key plays an extremely important role in updating the display. 2). In detail: When the data in the state changes, react will generate a [new virtual DOM] according to the [new data] Then React performs a diff comparison between [New Virtual DOM] and [Old Virtual DOM]. The comparison rules are as follows: a. The same key as the new virtual DOM is found in the old virtual DOM: (1). If the content in the virtual DOM has not changed, use the previous real DOM directly (2). If the content in the virtual DOM changes, a new real DOM will be generated, and then the previous real DOM in the page will be replaced b. The same key as the new virtual DOM was not found in the old virtual DOM Create a new real DOM based on the data, and then render it to the page \t\t\t\t\t\t\t\t\t 2. Possible problems caused by using index as key: 1. If the data is destroyed in sequence operations such as adding in reverse order and deleting in reverse order: It will generate unnecessary real DOM updates ==> The interface effect is fine, but the efficiency is low. 2. If the structure also contains the DOM of the input class: Will produce an error DOM update ==> There is a problem with the interface. 3. Attention! If there are no operations that destroy the order of data such as reverse order addition and reverse order deletion, It is only used to render the list for display, and there is no problem with using index as the key. 3. How to choose a key during development?: 1. It is best to use the unique identifier of each piece of data as the key, such as id, mobile phone number, ID number, student number and other unique values. 2. If it is determined that the data is simply displayed, it is also possible to use the index.
the code
<div id="test"></div> <script type="text/babel"> class Person extends React. Component{<!-- --> state = {<!-- --> persons:[ {<!-- -->id:1,name:'Xiao Zhang',age:18}, {<!-- -->id:2,name:'Xiao Li',age:19}, ] } add = ()=>{<!-- --> const {<!-- -->persons} = this.state const p = {<!-- -->id:persons.length + 1,name:'Xiao Wang',age:20} this.setState({<!-- -->persons:[p,...persons]}) } render(){<!-- --> return ( <div> <h2>Display personnel information</h2> <button onClick={<!-- -->this.add}>Add a little king</button> <h3>Use index (index value) as key</h3> <ul> {<!-- --> this.state.persons.map((personObj,index)=>{<!-- --> return <li key={<!-- -->index}>{<!-- -->personObj.name}---{<!-- -->personObj.age}<input type="text "/></li> }) } \t\t\t\t\t</ul> <hr/> <hr/> <h3>Use id (the unique identifier of the data) as the key</h3> <ul> {<!-- --> this.state.persons.map((personObj)=>{<!-- --> return <li key={<!-- -->personObj.id}>{<!-- -->personObj.name}---{<!-- -->personObj.age}<input type=\ "text"/></li> }) } \t\t\t\t\t</ul> </div> ) } } ReactDOM.render(<Person/>,document.getElementById('test')) </script>
Rendering
Description
/* Slow motion playback----use the index index value as the key \t\t\tInitial data: {id:1,name:'Xiao Zhang',age:18}, {id:2,name:'Xiao Li',age:19}, Initial virtual DOM: <li key=0>Xiao Zhang---18<input type="text"/></li> <li key=1>Xiao Li---19<input type="text"/></li> Updated data: {id:3,name:'Xiao Wang',age:20}, {id:1,name:'Xiao Zhang',age:18}, {id:2,name:'Xiao Li',age:19}, Virtual DOM after updating data: <li key=0>Xiao Wang---20<input type="text"/></li> <li key=1>Xiao Zhang---18<input type="text"/></li> <li key=2>Xiao Li---19<input type="text"/></li> -------------------------------------------------- --------------- Slow motion playback----Use id unique identification as key \t\t\tInitial data: {id:1,name:'Xiao Zhang',age:18}, {id:2,name:'Xiao Li',age:19}, Initial virtual DOM: <li key=1>Xiao Zhang---18<input type="text"/></li> <li key=2>Xiao Li---19<input type="text"/></li> Updated data: {id:3,name:'Xiao Wang',age:20}, {id:1,name:'Xiao Zhang',age:18}, {id:2,name:'Xiao Li',age:19}, Virtual DOM after updating data: <li key=3>Xiao Wang---20<input type="text"/></li> <li key=1>Xiao Zhang---18<input type="text"/></li> <li key=2>Xiao Li---19<input type="text"/></li> */