9
头图

Hi everyone, I'm Kasong.

Yesterday a Demo sent me a 06145bfbc20310, let me explain the reason.

Demo a look, good guy, the little one is 06145bfbc2032a, the knowledge points are included:

  • Hooks 's closure problem
  • state is 06145bfbc20396 assembled

I believe that if you understand this Demo , you will have a deeper understanding function components.

Confusing Demo

Demo contains a button and a list.

 <div className="App">
    <button onClick={add}>Add</button>
    {list.map(val => val)}
  </div>

Click the button to call the add method to insert an item into the list:


let i = 0;

export default function App() {
  const [list, setList] = useState([]);

  const add = () => {
    // ...
  };

  return (
    <div className="App">
      <button onClick={add}>Add</button>
      {list.map(val => val)}
    </div>
  );
}

display effect:

Local burning of the brain that calls add method is to insert a button calls the add method click :

const add = () => {
    setList(
      list.concat(
        <button 
          key={i} 
          onClick={add}>
          {i++}
        </button>
      )
    );
  };

The display effect after clicking the Add

So the question is, what will be the effect after clicking the button with a number (which will call add method the same as Add button)?

State assembly and closure problems

If you think you will insert a new button:

That would be wrong.

The correct answer is: After clicking the corresponding button, the length list button corresponding number + 1 , and the number of the last item is largest number before clicking + 1 .

For example, the maximum number before clicking is 6

If you click 0, the length of list 0 + 1 = 1 , and the last item is 6 + 1 = 7 :

If you click 2, the length of list 2 + 1 = 3 , and the last item is 6 + 1 = 7 :

This is the result of two factors:

  • Hooks closure problem
  • state is 06145bfbc20699 assembled

Cause Analysis

Let's take a look at the add method:

const add = () => {
    setList(
      list.concat(
        <button 
          key={i} 
          onClick={add}>
          {i++}
        </button>
      )
    );
  };

button click to call add , it will be based on add relevant context ( App formed closure function), the closure comprising:

  • add
  • list
  • setList

i belongs to the module level, not in the closure

Among them, list and setList come from the return value after calling useState

const [list, setList] = useState([]);

A common cognitive errors are: multiple calls useState returned list is the same references.

In fact, the useState returned by list is calculated based on the following formula:

Base state + update1 + update2 + ... = current state

So it is a brand new object.

If you want to know more about the calculation details of update and state React Technology Revealed

When rendered on the first screen:

  1. App component for the first time render
  2. Create list = []
  3. <button onClick={add}>Add</button> depends on add to form a closure, and the closure is list = []

Next, click the Add button:

  1. Call the add method, which comes from the closure created by first screen rendering
  2. add process dependent list from the same closure, so list = []
  3. <button key={i} onClick={add}>{i++}</button> depends on add to form a closure. The list = []

So, for button 0,

Whenever you click, what he actually performs is:

setList(
  [].concat(
    <button key={i} onClick={add}>{i++}</button>
  )
);

So how to fix this problem is also very simple, change setList to the function form:

// 之前
setList(list.concat(<button key={i} onClick={add}>{i++}</button>));
// 之后
setList(list => list.concat(<button key={i} onClick={add}>{i++}</button>));

list in the function parameter Hooks saved in list , not list in the closure.

Summarize

Since Hooks always calculates the new state when the component is render , this brings a heavier mental burden Hooks

In contrast, using fine-grained update achieve Hooks (such as VUE Composition API ) can update the status in real time, and the operation is more intuitive.

In the Hooks , have you encountered similar headaches?

Welcome to join the human high-quality front-end framework research group , lead the flight


卡颂
3.1k 声望16.7k 粉丝