Dogtiti / Blogs

:sparkling_heart:一起记笔记呀~
8 stars 6 forks source link

使用useState更新不同对象,react hooks是怎么区分更新哪一个的? #57

Open yixiaosi1314 opened 3 years ago

zyb970821 commented 3 years ago

1、useState是什么?

是一个react提供的hook函数,可以让函数组件具有状态管理的功能。

例如:一个无状态组件

import React from 'react';

function Bulbs() {
  return <div className="bulb-off" />;
}

第一步:启用状态(引入钩子)

伪代码如下

import React, { useState } from 'react';

function Bulbs() {
  ... = useState(...);
  return <div className="bulb-off" />;
}

第二步:初始化状态

import React, { useState } from 'react';

function Bulbs() {
  ... = useState(false);
  return <div className="bulb-off" />;
}

可以通过打印useState(false);

第三步:读取状态

const stateArray = useState(false);
stateArray[0]; // => 状态值

当 hook useState(initialState)被调用时,它返回一个数组,该数组的第一项是状态值,在组件里面读取:

function Bulbs() {
  const stateArray = useState(false);
  return <div className={stateArray[0] ? 'bulb-on' : 'bulb-off'} />;
}

第四步:更新状态

useState返回一个数组,其中第一项是一个状态值,第二项是一个更新状态的函数,可以通过解构赋值来进行编写:

const [state, setState] = useState(initialState);

// 将状态更改为 'newState' 并触发重新渲染
setState(newState);

// 重新渲染`state`后的值为`newState`

要更新组件的状态,请使用新状态调用更新器函数setState(newState)。组件重新渲染后,状态接收新值newState

伪代码如下:

import React, { useState } from 'react';

function Bulbs() {
  const [on, setOn] = useState(false);

  const lightOn = () => setOn(true);
  const lightOff = () => setOn(false);

  return (
    <>
      <div className={on ? 'bulb-on' : 'bulb-off'} />
      <button onClick={lightOn}>开灯</button>
      <button onClick={lightOff}>关灯</button>
    </>
  );
}

也可以通过回调来更新状态:

const [state, setState] = useState(initialState);
...
setState(prevState => nextState);

2、怎么区分不同对象的useState?

因为JavaScript是单线程的,在usestate它被调用时,如果一个组件有多次 usestate ,useState必须按照规定数量和顺序被调用,只有第一次传入参数是有效的,那么就会按照顺序一次返回。

function App(){
      const [num, setNum] = useState(0);
      const [name, setName] = useState('ashen');
      const [age, setAge] = useState(21);
}

currentRenderingFiber.memorizedState中保存一条hook对应数据的单向链表。

const hookNum = {
      memorizedState: null,
      next: hookName
}
hookName.next = hookAge;
currentRenderingFiber.memorizedState.next = hookNum;

当函数组件渲染时,每执行到一个hook,就会将currentRenderingFiber.memorizedState的指针向后移一下。这也是hook的调用顺序不能改变的原因(不能在条件语句中使用hook)。