How React Hooks Work

How React Hooks Work

1. React Hooks vs. Pure Functions

To put it simply, React Hook is some new APIs added in React V18.6. The essence of API is to provide a function interface for certain functions. Therefore, React Hooks are functions, but React Hooks are not pure functions.

What is a pure function? That is, this function must produce the same output when the input value is the same, and this function cannot affect external data.
Simply put, variables defined outside cannot be used inside a function, because if variables defined outside are used, when the external variables change, it will affect the calculation inside the function, and the function will also affect the external variables.

The functional API provided by React Hooks is not a pure function.
Let’s look at a useState statement const [count, setCount] = useState(0). The results of using the useState function are not always the same, because if the result of useState(0) is the same every time, then the count value will never change, and the page where the count is located will never change, which is different from the result we see. From this we can see that React Hooks are not pure functions, which means that Hooks use variables outside of functions.

So what is it that makes React Hooks not pure functions? In fact, it is determined by the React framework and the function component itself. We know that the principle of React page rendering is to get a new virtual DOM each time you render, and then perform DOM Diff to render the page. React's functional component gets a virtual DOM by executing the entire function. Therefore, every time the page is rendered, all statements inside the function component will be re-executed. If the React Hooks used inside the functional component are pure functions, you will not get a different virtual DOM after each rendering.

React stipulates that all React components must be pure functions and are prohibited from modifying their own props.

Therefore, before React V16.8, when React Hooks were not yet released, function components, because they were pure functions, could only return a fixed virtual DOM, could not contain states, and did not support lifecycle methods. Therefore, at that time, only function components were supported. However, function components had too many restrictions compared to class components. Function components could not replace class components, nor were they as easy to use as class components.

React wants components to be simple rather than complex. React believes that the best way to write components should be functions rather than classes. Therefore, React added React Hooks. Hook means hook, which is provided by React to function components to "hook" external functions and data status when they are needed, thereby improving function components and enabling them to completely replace class components.

React's function components can only be pure functions, so the task of getting a different virtual DOM when re-rendering the function components every time an event occurs is completely left to React Hooks. So how does React Hooks do it? Next, we will manually implement a useState. The specific details of useState are definitely different, but the principles and ideas are the same.

2. Simple myUseState

The first execution of React.useState assigns the initial value to a _state, and each subsequent re-render reads the value of _state. What setState in [state, setState] does is to change the value of _state and then re-render the page.
According to this principle, the myUseState function is implemented as follows:

import React from 'react';
import ReactDOM from 'react-dom';

let _state

function myUseState(initialValue){
  if(_state === undefined){
    _state = initialValue
  }
  const setState = (newValue)=>{
    _state = newValue
    render()
  }
  return [_state, setState]
}

function render(){
  ReactDOM.render(<App/>,document.getElementById('root'));
}

function App(){
  const [n, setN] = myUseState(0)
  return (
    <div>
      n: {n}
      <button onClick={() => setN(n+1)}>+1</button>
    </div>
  )
}

ReactDOM.render(<App/>,document.getElementById('root'));

3. Improve myUseState

The myUseState implemented above has a bug. When myUseState is used twice in a function component, a problem will occur. The two will share the same _state, which will cause confusion.
Therefore, the above implementation needs to be improved. The idea of ​​improvement is to define _state as a data or object. Since we only pass a numerical value when using the function, we cannot determine the key value, so we can only use the data. The improvements are as follows:

import React from 'react';
import ReactDOM from 'react-dom';

let _state = []
let index = 0

function myUseState(initialValue){
  const currentIndex = index
  if(_state[currentIndex] === undefined){
    _state[currentIndex] = initialValue
  }
  const setState = (newValue)=>{
    _state[currentIndex] = newValue
    render()
  }
  index++
  return [_state[currentIndex], setState]
}

function render(){
  index = 0
  ReactDOM.render(<App/>,document.getElementById('root'));
}

function App(){
  const [n, setN] = myUseState(0)
  const [m, setM] = myUseState(0)
  return (
    <div>
      n: {n}
      <button onClick={() => setN(n+1)}>+1</button>
      <br/>
      m: {m}
      <button onClick={() => setM(m+1)}>+1</button>
    </div>
  )
}

ReactDOM.render(<App/>,document.getElementById('root'));

4. Hooks rules triggered by implementation principles

The myUseState implemented above is definitely not the specific implementation code of React.useState, but the implementation principle is the same. The myUseState function encapsulates the data state within the function component and manages the state, exposing the relevant operation interface for the function component to use.
In this way, the function component is separated from its data state. The function component is only responsible for returning the virtual DOM itself, and the management of the data state is completely handed over to the React.useState Hook to which it is "hooked".

From the above implementation ideas, we can find that the implementation of React Hooks is actually a special function based on global variables and closure principles.

However, it is precisely because of this implementation method that the use of React Hooks is limited to calling Hooks only at the top level, which means that Hooks should not be called in loops, conditions, or nested functions. If Hooks are used in if conditional statements, the number of executions of the React.useState statement will be incorrect each time the component is rendered, which will disrupt the index count and cause data maintenance errors.

The above implementation principle relies on the correct counting of indexes, so React relies on the order in which Hooks are called.

The above is a detailed explanation of how React Hooks work. For more information about React Hooks, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Detailed explanation of how to pass values ​​between react hooks components (using ts)
  • ReactHooks batch update state and get route parameters example analysis
  • React Hooks Detailed Explanation
  • Common pitfalls of using React Hooks
  • 30 minutes to give you a comprehensive understanding of React Hooks
  • Common usage of hook in react
  • Introduction to 10 Hooks in React

<<:  Using MySQL database with Python 3.4 under Windows 7

>>:  Django uses pillow to simply set up verification code function (python)

Recommend

Problems and solutions of using TweenMax animation library in angular

I have nothing to do recently, so I tinker with C...

Vue achieves seamless carousel effect (marquee)

This article example shares the specific code of ...

CSS naming conventions (rules) worth collecting Commonly used CSS naming rules

CSS naming conventions (rules) Commonly used CSS ...

jQuery combined with CSS to achieve the return to top function

CSS Operations CSS $("").css(name|pro|[...

Vue implements multi-grid input box on mobile terminal

Recently, the company has put forward a requireme...

Vue implements sample code to disable browser from remembering password function

Find information Some methods found on the Intern...

Causes and solutions for slow MySQL queries

There are many reasons for slow query speed, the ...

SQL ROW_NUMBER() and OVER() method case study

Syntax format: row_number() over(partition by gro...

MySQL 8.0.18 installation and configuration method graphic tutorial

This article records the installation and configu...

Sample code for highlighting search keywords in WeChat mini program

1. Introduction When you encounter a requirement ...

Solve the problem of docker pull image error

describe: Install VM under Windows 10, run Docker...

How to use bind to set up DNS server

DNS (Domain Name Server) is a server that convert...