React Hooks was released when react version 16.8.0 was released in 2018. So far, it is not a new technology. Now react version has reached 17.0.2. However, I believe many people like me have only heard about React Hooks and have not yet understood what it is and how to use it in the project. Let's get to know it now.
Before the emergence of React Hooks, we divided react components into class components and stateless components. Class components are class components, which can define state and have a life cycle to deal with complex businesses; Stateless components are pure functions, which are mainly used for page rendering. There is no life cycle and state, and there is no complex this.
With the emergence of hooks, components are now only divided into class components and function components, which can define state and side effects. We often call network requests, DOM operations, event listening and unbinding as side effects. The side effects of class components are executed in various life cycle functions, while hooks has no life cycle of class components, However, there are hooks that are used to replace the lifecycle.
Hook It is a new feature of React 16.8. It allows you to use state and other React features without writing class. (official website)
Hook is a function that allows you to "hook in" React state, life cycle and other features in the function component. Hook cannot be used in the class component - this allows you to use React without using class. (official website)
catalogue
1.State Hook
React provides some built-in Hooks. Let's learn State Hooks and useState first. Next, we use class components and Hook to implement a counter.
import React ,{ Component } from 'react'; class App extends React.Component { constructor(props){ super(props); this.state = { count: 0 } } render(){ let { count } = this.state; return ( <div> <p>You clicked {count} times</p> <button onClick={() => this.setState({count: count + 1})}> Click me </button> </div> ) } }
import React ,{ useState } from 'react'; function App(){ const [count,setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ) }
Through comparison, we can see that the implementation code of Hook will be more concise. useState is a Hook function. Its only parameter is the initialization state, which can be a number, string, object, array or function. This initialization state is only used in the first rendering. useState will return a pair of values, the current state and a function that allows you to update it. Similar to setState of class components, the variable name of the returned value is arbitrary, but the update function basically starts with set.
If the initial value of state comes from props, the function can be used to initialize state, so it will not run every time the component is re rendered, as follows:
import React ,{ useState } from 'react'; function App(props){ const [count,setCount] = useState(() => { return props.index }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ) }
According to business needs, we sometimes need to declare multiple state s, as follows:
function App(props){ const [count,setCount] = useState(0); const [name,setName] = useState('tom'); const [todos,setTodos] = useState([{text: 'learn hooks'}]) ... }
2.Effect Hook
useEffect It is an Effect Hook, which adds the ability of operating side effects to function components. It is similar to the componentDidMount,componentDidUpdate and componentWillUnmount It has the same purpose, but it is merged into one API. (official website)
Next, we use class components and Hook to realize real-time Title Update, click times and screen size event monitoring.
import React ,{ Component } from 'react'; class App extends React.Component { constructor(props){ super(props); this.state = { count: 0, view: { height: document.documentElement.clientHeight, width: document.documentElement.clientWidth } } } resize = () => { this.setState({ view: { height: document.documentElement.clientHeight, width: document.documentElement.clientWidth } }) } componentDidMount(){ document.title = this.state.count; window.addEventListener('resize',this.resize) } componentDidUpdate(){ document.title = this.state.count; } componentWillUnmount(){ window.removeEventListener('resize',this.resize) } render(){ let { count, view } = this.state; return ( <div> <p>You clicked {count} times</p> <button onClick={() => this.setState({count: count + 1})}> Click me </button> <p>Width:{view.width} Height:{view.height}</p> </div> ) } }
import React ,{ useState, useEffect } from 'react'; function App(){ const [count,setCount] = useState(0); const [view,setView] = useState({ height: document.documentElement.clientHeight, width: document.documentElement.clientWidth }) useEffect(()=>{ document.title = count; }) const resize = () => { setView({ height: document.documentElement.clientHeight, width: document.documentElement.clientWidth }) } useEffect(()=>{ window.addEventListener('resize',resize); return () => { window.removeEventListener('resize',resize) } }) return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> <p>Width:{view.width} Height:{view.height}</p> </div> ) }
In the above class, we are in componentDidMount and The same code for setting the title is written in the componentDidUpdate lifecycle function, because we need to perform the same operation when the component is loaded and updated.
In the Hook above, we wrote two useeffects, each of which deals with a side effect. The first effect is equivalent to the effect in the class component componentDidMount and Compositional function of componentDidUpdate; The second effect is equivalent to componentDidMount and componentWillUnmount. These two effects are executed every time you render.
The useEffect function returns a function. React will call it when the cleanup operation is performed, and react will perform the cleanup operation when the component is unloaded.
The second input parameter of the useEffect function is an array. If the second parameter is not passed in, the useEffect will be triggered every time the component is updated; The second parameter is passed into [] empty array. The effect will only be triggered during initialization, and component re rendering will not trigger this effect.
useEffect(()=>{ console.log('run') },[count])
In the above example, we pass in [count] As the second parameter. What is the function of this parameter? If count The value of is 5, and when our components are re rendered count Or equal to 5. React will update the previous rendering [5] And the last rendered [5] Compare. Because all elements in the array are equal (5 = = = 5), react will skip this effect, which realizes performance optimization.
When rendering, if count The value of is updated to 6. React will the array of the previous rendering [5] And the array rendered this time [6] Compare the elements in. This time because 5 !== 6. React will call effect again. If there are multiple elements in the array, react will execute effect even if only one element changes.
3. Customize Hook
Custom Hook is a function whose name starts with "use". Other hooks can be called inside the function. The following is an example of a custom Hook.
function useResize(){ const [view,setView] = useState({ height: document.documentElement.clientHeight, width: document.documentElement.clientWidth }) const resize = () => { setView({ height: document.documentElement.clientHeight, width: document.documentElement.clientWidth }) } useEffect(()=>{ window.addEventListener('resize',resize); return () => { window.removeEventListener('resize',resize) } }) return view; }
The above custom Hook is used to set the window size and return an object with the attributes of height and width. Now let's take a look at how to use custom Hook
function App(){ const view = useResize(); return ( <div> <p>Width:{view.width} Height:{view.height}</p> </div> ) }
This code is exactly the same as the code of the original example. We just extract some common code between the two functions into a separate function.
- Custom hooks must start with use, otherwise React will not be able to automatically check whether your Hook violates Hook rules.
- Using the same custom Hook in the two components will not share the state. The custom Hook is a mechanism for reusing the state logic (for example, setting it as a subscription and storing the current value). Therefore, every time the custom Hook is used, all States and side effects are completely isolated.
- Each call to Hook will get an independent state
4.Hook usage rules
Hook s are JavaScript functions, but there are two additional rules for using them:
- Hook can only be called on the outermost layer of a function. Do not call in loops, conditional judgement, or subfunctions.
- Only in Hook is called in the function component of React. Do not call in other JavaScript functions. (there is another place to call hook -- in the custom hook)