This is a translation, if you want to read the original, please click -> the original link
React Hooks have been around for a while and some developers haven’t started using them yet, I think for two main reasons:
- React developers are working on large applications that take a lot of time to migrate;
- Most of you are already familiar with Class Component writing, so it’s an easy way to continue.
In this article, I will list six benefits of using React Hooks
1. When a function Component gets bigger, you don’t need to refactor it as a Class Component
Typically, when we split a page, we pull out components that rely only on props, or puppet components. As functionality increases, the puppet Component may need to introduce state, and we have to refactor it into a Class Component. In the case of Hooks, functionality components also have the ability to access State, and such refactoring is minimal. Like the following puppet component that shows numbers:
export function(props) {
return (
<div>Count: {props.count}</div>)}Copy the code
When we add a requirement that count be +1 with each mouse click, and that count be changed only in the current Component, no other components are affected, we need to introduce state. Here’s a Class Component-based implementation:
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0}}componentDidMount() {
this.setState({ count: this.props.count })
}
render() {
return (
<div>Count: {this.state.count}</div>)}}Copy the code
If we do the same thing with Hooks:
const Counter = (props) = > {
const [count, setCount] = useState(0);
useEffect(() = > {
setCount(props.count)
}, [])
return (
<div>Count: {count}</div>)}Copy the code
You don’t need to worry about this anymore
Can confuse both people and machines Classes
The above quote comes fromReactIf you’re familiar with Javascript, you know that this works differently in Javascript than it does in other languages. When you start using Hooks, you don’t need to worry about this anymore. This is friendly to beginners and experienced developers.
3. You don’t need bind anymore
Continue adding the add count function to the previous component:
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
this.handleClickEvent = this.handleClickEvent.bind(this)}componentDidMount() {
this.setState({ count: this.props.count })
}
handleClickEvent = () = > {
this.setState({count: this.props.count + 1})}render() {
return (
<div onClick={this.handleClickEvent}>Count: {this.state.count}</div>)}}Copy the code
This requires first adding a method to increment the count. In order to use this method properly, we need to bind this from constructor:
this.handleClickEvnet = this.handleClickEvent.bind(this)
Copy the code
Because the execution context of the function changes when the click event is triggered, so that this in the method is not the current class, we have to bind this, which may be confusing to beginners. Of course, there are other ways to achieve similar effects besides using this for binding, such as the arrow function:
handleClickEvent = () = > {
this.setState({ count: this.state.count + 1})}Copy the code
Let’s see how Hooks implement this:
count Counter = (props) = > {
const [count, setCount] = useState(0);
useEffect(() = > {
setCount(props.count)
}, [])
function handleClickEvent() {
setCount(count + 1)}return (
<div onClick={handleClickEvent}>Count: {count}</div>)}Copy the code
As you can see, in Hooks we simply add a method and bind it to the corresponding node, we don’t need this at all
4. Make the UI and logic more easily decoupled and reusable
Make it easier to separate UI and logic with Hooks, no need for HOC and render props, Hooks can combine UI and logic with less boilerplate code, and more elegant UI.
When you’re usingBit.GithubThis “elegant separation” is especially important when such code-sharing platforms share your components, making them easier to understand, maintain, and reuse across different applications.
5. Keep the related logic in the same place
Complex components become hard to understand
ComponentDidMount, componentDidUpdate, etc. Let’s think about A scenario where we subscribe to A and B services in componentDidMount. And unsubscribe in componentWillUnMount, and there’s a lot of other logic in both life cycles that makes it hard to relate subscriptions that are distributed across both life cycles to unsubscribe when we look back at the code. To prove this, we created a counting application using Rxjs, and we no longer need the handleClickEvent method
import { Subject } from 'rxjs'
export function getCounts() {
const subject = new Subject()
let count = 0;
const interval = setInterval(() = > {
if (count > 10 || subject.isStopped) {
clearInterval(interval)
subject.complete()
}
subject.next(count++)
}, 1000)
return subject()
}
Copy the code
import { getCounts } from './reactive-service'
export function Counter(props) {
const [count, setCount] = useState();
useEffect(() = > {
const counterServiceSubject = getCounts();
counterServiceSubject.subscribe(c= > {
setCount(c)
})
return () = > {
counterServiceSubject.unsubscribe()
}
}, [])
return (
<div>Count: {count}</div>)}Copy the code
We can include subscribe and its corresponding unsubscribe logic in the same useEffect. Similarly, if you need other unrelated logic, you can put it in another useEffect. We can use different use effects to separate the different parts.
// ...
useEffect(() = > {
others.subscribe(() = > {
// do sth.
})
return () = > others.unsubscribe()
}, [])
// ...
Copy the code
6. Sharing state logic between different components
In class Component, even though two components have the same functionality, they may need to fetch data from different sources and use different rules to sort and present the data, making it difficult for them to share state logic. We could have done it with HOC, render props, etc., but it made it harder to tweak existing components.
What do React Hooks provide
With custom Hooks, you can extract this logic, isolate it into general logic, and test it separately. For example, we could separate count from the example above into an Hooks called useCount:
export function useCount(serviceSubject) {
const [count, setCount] = useState();
useEffect(() = > {
serviceSubject.subscribe(cnt= > {
setCount(cnt)
})
return () = > serviceSubject.unsubscribe()
}, [serviceSubject])
return [count, setCount];
}
Copy the code
It can then be used directly:
import { useCount } from "./use-count";
export function ShowCount(props) {
const [count, setCount] = useCount(props.serviceSubject);
useEffect(() = > {
setCount(props.count);
}, [setCount]);
return (
<div>
<h1> Count : {count} </h1>
</div>
);
}
Copy the code
Notice that we call getCounts in the parent component, not in the ShowCount component. Otherwise, serviceSubject will have a new value every time it runs ShowCount, and we won’t get the result we expect.
That’s why I switched to React Hooks. If you look at the official documentation, you’ll see that React Hooks have a number of interesting features. If React Hooks bring you other benefits, let me know in the comments section