Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

I hear you still don't know React Hook?

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

Hook is a new feature in React 16.8. It allows you to use state and other React features without writing class

From this sentence on the official website, we can clearly know that Hook has increased the use of state in functional components. In the past, functional components could not have their own state and could only render their own UI through props and context. In business logic, some scenarios must use state, so we can only define functional components as class components. Now with Hook, we can easily maintain our state in functional components without changing to class components.

The problem to be solved by React Hooks is state sharing, which refers to only sharing state logic reuse, not data sharing. We know that before React Hooks, we usually use higher-order components and render-props to solve the problem of state logic reuse, so why should React developers introduce React Hook when they already have these two solutions? What are the advantages over higher-order components and render-props,React Hook?

React Hook example

Let's first take a look at React Hook's demo officially given by React.

Import {useState} from 'React';function Example () {/ / Declare a new state variable, which we'll call "count" const [count, setCount] = useState (0); return (

You clicked {count} times

SetCount (count + 1)} > Click me);} copy the code

Let's take a look at how to implement it without React Hook.

Class Example extends React.Component {constructor (props) {super (props); this.state = {count: 0};} render () {return (

You clicked {this.state.count} times

This.setState ({count: this.state.count + 1})} > Click me);}} copy code

As you can see, in React Hook, the class Example component becomes a functional component, but this functional component has its own state and can update its own state at the same time. All thanks to useState, the Hook,useState returns a pair of values: the current state and a function that lets you update it, which you can call in the event handler or somewhere else. It is similar to the this.setState of the class component, but it does not merge the new state with the old state

The solution of reusing State Logic in React

Hook is another solution to reuse state logic. React developers have been putting forward and improving the reuse of state logic, from Mixin to high-level components to Render Props to the current Hook. Let's take a brief look at the previous solution.

Mixin mode

In the earliest days of React, it was proposed to reuse the logic between components according to the Mixin pattern. In Javascript, we can think of Mixin inheritance as a way to extend collection capabilities. Every new object we define has a prototype from which it can inherit more properties. Prototypes can be inherited from other objects, but more importantly, properties can be defined for any number of objects. We can take advantage of this fact to promote functional reuse.

Mixin in React is mainly used in two completely unrelated components, there is a set of basically similar functions, we can extract it and inject it through mixin, so as to achieve code reuse. For example, in different components, the component needs to be updated at regular intervals, and we can do this by creating the setInterval () function, which we need to uninstall when the component is destroyed. So you can create a simple mixin that provides a simple setInterval () function that is automatically cleaned up when the component is destroyed.

Var SetIntervalMixin = {componentWillMount: function () {this.intervals = [];}, setInterval: function () {this.intervals.push (setInterval.apply (null, arguments));}, componentWillUnmount: function () {this.intervals.forEach (clearInterval);}}; var createReactClass = require ('create-React-class'); var TickTock = createReactClass ({mixins: [SetIntervalMixin], / / use mixin getInitialState: function () {return {seconds: 0}) }, componentDidMount: function () {this.setInterval (this.tick, 1000); / / call method on mixin}, tick: function () {this.setState ({seconds: this.state.seconds + 1});}, render: function () {return (

React has been running for {this.state.seconds} seconds.

);}}); ReactDOM.render (, document.getElementById ('example')); copy the code

Shortcomings of mixin

Different mixin may be interdependent and too coupled, resulting in high maintenance costs in the later stage.

Naming in mixin may conflict and mixin with the same name cannot be used

Even if mixin is simple at the beginning, it will snowball over time as business scenarios increase.

Specific disadvantages can be seen in this link Mixins is a scourge

Because of these shortcomings of mixin, it is no longer recommended to use mixin mode to reuse code in React. React fully recommends using high-level components to replace mixin mode, and ES6 itself does not contain any mixin support. Therefore, when you use ES6 class in React, mixins will not be supported.

High-order component

High-level components (HOC) is an advanced technique for reusing component logic in React. HOC itself is not a part of React API, it is a design pattern based on the combined features of React.

High-level components are not the API provided by React, but a skill of React. High-level components can be seen as the implementation of Decorator Pattern in React. Decorator pattern: dynamically attach responsibilities to objects. To extend functionality, decorators provide a more flexible alternative than inheritance.

Specifically, a high-order component is a function in which the parameter is the component and the return value is the new component.

A component converts props to UI, while a high-level component converts a component into another component.

We can dynamically add log printing to other components through high-level components without affecting the functions of the original components.

Function logProps (WrappedComponent) {return class extends React.Component {componentWillReceiveProps (nextProps) {console.log ('Current props:', this.props); console.log ('Next props:', nextProps);} render () {return;}} copy the code

Render Propss

The term "Render Props" refers to a simple technique for sharing code between React components using prop with a value as a function.

Components with Render Props accept a function that returns a React element and calls it instead of implementing its own rendering logic

Below we provide a component with prop that dynamically determines what needs to be rendered so that the logic and state of the component can be reused without changing its rendering structure.

Class Cat extends React.Component {render () {const mouse = this.props.mouse; return (

);}} class Mouse extends React.Component {constructor (props) {super (props); this.handleMouseMove = this.handleMouseMove.bind (this); this.state = {x: 0, y: 0};} handleMouseMove (event) {this.setState ({x: event.clientX, y: event.clientY});} render () {return ({this.props.render (this.state)}) }} class MouseTracker extends React.Component {render () {return (move mouse! ()} / >);}} copy code

Usually, however, Render Props is called Render Props because of the schema, not because it is necessary to name prop with render. We can also express it this way.

{mouse = > ()} copy the code

React Hook motivation

React Hook is another brand-new solution proposed by the official website. Before we learn about React Hook, let's take a look at the motivation proposed by React Hook.

It is difficult to reuse state logic between components

Complex components become difficult to understand

Incomprehensible class

Here's my understanding of these three motivations:

It is difficult to reuse state logic between components. Previously, we used high-order components (Higher-Order Components) and rendering attributes (Render Propss) to solve the problem of state logic reuse. Many libraries use these patterns to reuse state logic, such as redux and React Router. High-level components and rendering attributes are all nested common components layer by layer through combination, which will greatly increase the hierarchical relationship of our code, resulting in excessive nesting. From React's devtool, we can clearly see the level of nesting caused by the use of these two modes.

Complex components become difficult to understand, and in the changing business requirements, components are gradually filled with state logic and side effects, and each lifecycle often contains some irrelevant logic. We usually write code according to the single principle of a function. A function usually does only one thing, but it usually does a lot of things at the same time in a lifecycle hook function. For example, when we need to initiate an ajax request in componentDidMount to get data, sometimes we write event bindings in this life cycle, and sometimes we even need to treat the data in the same way as componentDidMount in componentWillReceiveProps.

Code that is interrelated and needs to be modified against each other is split, while completely unrelated code is grouped together in the same method. This makes it easy to generate bug and lead to logical inconsistencies.

It is difficult to understand class. Personally, I think it is OK to use class components. As long as you understand the binding problem of class's this, it is not difficult to get started. You have to understand that this is not a specific behavior of React; it actually has something to do with how the JavaScript function works. So as long as you understand how JS functions work, this binding is not a problem. It's just that sometimes in order to make sure that the this is pointing correctly, we usually write a lot of code to bind the this, and if we forget to bind, there will be all kinds of bug. Bind the this method:

1.this.handleClick = this.handleClick.bind (this); 2. This.handleClick (e)} > Click me copy code

So in order to solve the above problems, React Hook was put forward.

State Hook usage

Let's go back to the code just now and see how to define state in a functional component

Import React, {useState} from 'React';const [count, setCount] = useState (0); copy the code

What did useState do?

We can see that in this function, we define a 'state variable' through useState, which is exactly the same as the function provided by this.state in class. This is equivalent to the following code

Class Example extends React.Component {constructor (props) {super (props); this.state = {count: 0};} copy the code

UseState parameter

In the code, we pass in 0 as the parameter of useState, and the value of this parameter will be regarded as the initial value of count. Of course, this parameter is not limited to passing numbers and strings, you can pass in an object as the initial state. If state needs to store the values of multiple variables, you can call useState multiple times.

UseState return value

The return value is: the current state and the function to update state, which is similar to this.state.count and this.setState in class, except that you need to get them in pairs. If you look at [count, setCount], it's easy to see that this is the way ES6's deconstructed array is written. This is equivalent to the following code

Let _ useState = useState (0); / / returns an array of two elements let count = _ useState [0]; / / the first value in the array let setCount = _ useState [1]; / / the second value in the array copies the code

Read status valu

You just need to use variables.

The previous way of writing

You clicked {this.state.count} times

Copy the code

The way to write now

You clicked {count} times

Copy the code

Update status

Update through the setCount function

The previous way of writing

This.setState ({count: this.state.count + 1})} > Click me copy code

The way to write now

SetCount (count + 1)} > Click me copy code

Here the parameters received by setCount are the modified new state values

Declare multiple state variables

We can use state Hook multiple times in a component to declare multiple state variables

Function ExampleWithManyStates () {/ / declares multiple state variables! Const [age, setAge] = useState (42); const [fruit, setFruit] = useState ('banana'); const [todos, setTodos] = useState ([{text:' Learn Hooks'}]); / /.} copy the code

React assumes that when you call useState multiple times, you can guarantee that the order in which they are called remains the same each time you render.

Why does React stipulate that the order of calls to them remains the same each time they are rendered? this is a crucial question for understanding Hook.

Hook rule

Hook is essentially a JavaScript function, but there are two rules to follow when using it. And React requires that these two rules be enforced, otherwise an abnormal bug will occur.

Use Hook only at the top level

Do not call Hook in loops, conditions, or nested functions, make sure they are always called at the top level of your React function

Only call Hook in the React function

Do not call Hook in ordinary JavaScript functions

The reason for these two rules is that we can use multiple State Hook or Effect Hook,React in a single component to know which state corresponds to which useState by the order of Hook calls.

Function Form () {const [name1, setName1] = useState ('Arzh2'); const [name2, setName2] = useState (' Arzh3'); const [name3, setName3] = useState ('Arzh4'); /...} /-/ first render / /-useState (' Arzh2') / / 1. Initialize the variable stateuseState ('Arzh3') / / 2 with the name of name1 with' Arzh2'. Initialize the variable stateuseEffect ('Arzh4') / / 3 with the name of name2 with' Arzh3'. Use 'Arzh4' to initialize the state//-/ / secondary render / /-useState (' Arzh2') / / 1 with the variable name3. Read the state (parameter ignored) useState ('Arzh3') / / 2 with the variable name name1. Read the state (parameter ignored) useEffect ('Arzh4') / / 3 with the variable name name2. Read the state (parameter ignored) copy code with the variable name name3

If we violate the rules of React, use conditional rendering

If (name! = =') {const [name2, setName2] = useState ('Arzh3');} copy the code

Assuming that the first time (name! = ='') is true, execute this Hook, and when the second rendering (name! = ='') is false, do not execute this Hook, then the calling order of Hook will be changed, resulting in bug

UseState ('Arzh2') / / 1. Read the variable state//useState ('Arzh3') / / 2. Hook is ignored useEffect (' Arzh4') / / 3. Read the state copy code with the variable name name2 (formerly name3)

React doesn't know what the Hook of the second useState should return. React will assume that the call to the second Hook in this component corresponds to the useState of arzh3, just like the last rendering, but it is not. So that's why React forces Hook usage to follow these two rules, and we can use eslint-plugin-React-Hooks to enforce constraints.

Effect Hook usage

We added Effect Hook to the above code, added side effects to functional components, and modified the title of the page.

UseEffect (() = > {document.title = `You clicked ${count} times`;}); copy code

If you are familiar with React class's lifecycle functions, you can think of useEffect Hook as a combination of componentDidMount,componentDidUpdate and componentWillUnmount.

That is, we can use useEffect to replace these three life hook functions.

Let's take a look at scenarios that usually require side effects, such as sending requests, manually changing dom, logging, and so on. We usually invoke our side effects when the first dom rendering is completed and when the dom is updated later. We can take a look at the previous life cycle implementation.

ComponentDidMount () {document.title = `You clicked ${this.state.count} times`;} componentDidUpdate () {document.title = `times`;} copy the code

This is one of the second sources of the React Hook motivation we mentioned above, which requires the same code to be invoked in the first and subsequent renderings.

By default, Effect is executed after the first rendering and after each update, so we no longer need to consider whether to execute componentDidMount or componentDidUpdate, we just need to understand that Effect is executed after component rendering

Removal of side effects

Sometimes we need to remove some side effects, for example, we have a requirement to poll the server for the latest status, then we need to clean up the polling operation when uninstalling.

ComponentDidMount () {this.pollingNewStatus ()} componentWillUnmount () {this.unPollingNewStatus ()} copy the code

We can use Effect to remove these side effects by simply returning a function in Effect

UseEffect (() = > {pollingNewStatus () / / tells React to execute cleanup () return function cleanup () {unPollingNewStatus ()};}) before each rendering; copy the code

One obvious difference is that useEffect actually executes cleanup () before each rendering, while componentWillUnmount executes it only once.

Effect performance optimization

UseEffect is actually performed with every update, which in some cases can cause performance problems. Then we can optimize performance by skipping Effect. In the class component, we can solve the problem by adding comparison logic to prevProps or prevState in componentDidUpdate

ComponentDidUpdate (prevProps, prevState) {if (prevState.count! = = this.state.count) {document.title = `You clicked ${this.state.count} times`;}} copy the code

In Effect, we can just add the second parameter of Effect and skip the update if there is no change

UseEffect (() = > {document.title = `You clicked ${count} times`;}, [count]); / / updated only when count changes

For more information, add a little Coke.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report