Introduction to the
Hook is a new feature in Act 16.8 that lets you use features such as state, lifecycle, and so on without writing a class component.
motivation
Reusing state logic between components is difficult
There are some solutions to this problem, such as render props, higher-order components, Context, etc., that cause a tree of components to form a nested hell (a bit like the way callback functions and flutter are written).
With hooks, you can extract state logic from components so that it can be individually tested and reused. Hooks allow you to reuse state logic without modifying the component structure.
Complex components become difficult to understand
As the business expands, the number of logical states and side effects within components increases. When we write a class component, we usually put the data fetch in compoentDidMount and componentDidUpdate, and when it comes to timers or data subscriptions, You also need to clear timers or unsubscribe data in the life cycle function compoentWillUnmount. This makes the combination of completely unrelated code very buggy and illogical.
To solve this problem, hooks break the interrelated parts of a component into smaller functions (such as setting up subscriptions or requesting data) rather than enforcing a lifecycle partition.
Hard to understand class
Previously, if you wanted to use features like state, life cycles, etc., you had to introduce class components, and if you wanted to use them you had to take the time to understand how this works in JavaScript.
To address these issues, hooks allow you to use more React features in non-class situations.
An overview of
Hooks can be divided into built-in hooks and custom hooks.
Built-in hooks include:
- useState
- useEffect
- useContext
- useReducer
- useCallback
- useMome
- useRef
- useImperativeHandle
- useLayoutEffect
- useDebugValue
A custom Hook is a combination of the above built-in hooks and exported as a function starting with use.
Here we write a class based Counter component, let’s Hook it later.
import React from 'react'
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = { count: 0 }
this.setCount = this.setCount.bind(this)
}
setCount() {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<>
<h2>{ this.state.count }</h2>
<button onClick={ this.setCount} >+</button>
</>
)
}
}
Copy the code
useState
Let’s take a look at one of the most basic and equally important hooks, and now let’s start transforming the class component above.
- First of all to
class
Components tofunction
Components, that isFunctional component
.
- class Counter extends React.Component {}
+ function Counter() {}
Copy the code
- So let’s move on
state
And other relevant code to delete, insteaduseState
Hook, because there are many changes here, directly on the final code
import React, { useState } from 'react'
const Counter = (a)= > {
// Array destruct syntax
// Declare a count variable and declare a setCount function to change the value of count
const [count, setCount] = useState(0)
return (
<>
<h2>{ count }</h2>
<button onClick={() = > setCount(count + 1) }>+</button>
</>
)
}
Copy the code
At first glance, the code looks much cleaner, which is exactly what we want. (Hook smells good)
If we have more than one state variable, we can write it in the following form
const [count, setCount] = useState(0)
const [num, setNum] = useState(0)
const [name, setName] = useState(' ')
.
Copy the code
If this update depends on the last state value, it can be written that setCount takes a function as an argument
const [count, setCount] = useState(0)
const handleClick = (a)= > {
setCount(prev= > prev + 1)
}
<button onClick={ handleClick }>+</button>
Copy the code
useEffect
UseEffect allows you to perform side effects on a functional component. It takes two arguments, the first being the required side effect function and the second being the optional argument (which is an array of dependencies that the side effect function executes).
Again, if we want to perform some side effects after the component is updated, such as printing the value of the current count variable, or changing the title of the current page
// ...
const [count, setCount] = useState(0)
const [num, setNum] = useState(0)
useEffect((a)= > {
console.log('The current count value,${count}`)
document.title = 'The current count value,${count}`
})
// ...
Copy the code
In the code above we can see that we did not add a second optional argument, which means that this side effect function is executed whenever the state in the component changes (not just when count, but even when num changes). If we want the side effect function to be executed only when count changes, then our second argument will come in handy ()
// ...
// The current effect function only depends on the change of count, and is not executed when num changes
// equivalent to compoentDidMount and componentDidUpdate in the class component
useEffect((a)= > {
console.log('The current count value,${count}`)
document.title = 'The current count value,${count}`
}, [count])
// ...
Copy the code
If we only want the side effects function to execute when the component is mounted (compoentDidMount)
The useEffect convention, in which an empty array is passed as the second argument, executes the current side effect function only when the component is mounted
useEffect((a)= > {
console.log('The current count value,${count}`)
document.title = 'The current count value,${count}`
}, [])
Copy the code
Sometimes we might use a timer, like updating the time every second
const [time, setTime] = useState(new Date())
const timer = null
useEffect((a)= > {
timer = setInterval((a)= > {
setTime(new Date())
}, 1000)
})
Copy the code
UseEffect returns a function that is automatically executed when the component is uninstalled. UseEffect returns a function that is automatically executed when the component is unloaded. You can clear things like timers
const [time, setTime] = useState(new Date())
const timer = null
useEffect((a)= > {
timer = setInterval((a)= > {
setTime(new Date())
}, 1000)
// similar to compoentWillUnMount
// It can also be a named function
return (a)= > {
clearInterval(timer)
timer = null
}
})
Copy the code