深入浅出useState

1.setState会将多个setState合并成一个,以最后一个优先;

React 采用批量更新机制,setState 并不会立刻修改 state,而是等待下一次渲染时更新

当调用 setState 在当前执行上下文中是获取不到最新的 state, 只有在下一次组件 rerender 中才能获取到

setState 除了能传递一个值外,还可以传入回调函数,回调函数的参数就是最新的 state 的值

更新状态会触发组件重新渲染

      function App() {
        const [count1, setCount1] = React.useState(0)
        const handleClick1 = () => {
          setCount1(count1 + 1)
          setCount1(count1 + 1)
          console.log(count1)
        }

        const [count2, setCount2] = React.useState(0)
        const handleClick2 = () => {
          setCount2((count2) => {
            return count2 + 1
          })
          setCount2((count2) => {
            return count2 + 1
          })
        }

        console.log('我是render')

        return (
          <div>
            <p>You clicked {count1} times</p>
            <button onClick={handleClick1}>Click me</button>
            <p>You clicked {count2} times</p>
            <button onClick={handleClick2}>Click me</button>
          </div>
        )
      }

初始化的时候:我是render

每次点击handleClick1都只会count1+1

每次点击handleClick2都会count2+2

 

2.useState 的初始值有两种情况:第一种情况是非函数,将作为 state 初始化的值;

第二种情况是函数,函数的返回值作为 useState初始化的值,只在组件首次渲染时生效,为同步代码。

      function App() {
        const handleClick = () => {
          setName(6666)
        }

        const [name, setName] = React.useState(() => {
          console.log('init name state')
          return 'LinDaiDai'
        })

        console.log('我是render')

        const [name2, setName2] = React.useState(() => {
          console.log('init name2 state')
          return 'LinDaiDai2'
        })

        return (
          <div>
            <p>{name}</p>
            <button onClick={handleClick}>Click me</button>
          </div>
        )
      }

初始化:

init name state
我是render
init name2 state

点击handleClick:

我是render

 

 

3.useState 的初始值传递的如果是函数中的计算内容,那么这个计算会在每次渲染的时候都执行,但不会重新赋值

      let nums = 0
      function App() {
        const [count, setCount] = React.useState(0)

        function getNum() {
          nums = nums + 1
          console.log('getNum', nums)
          return nums
        }
        const [count2, setCount2] = React.useState(getNum() * 10)

        const handleClick1 = () => {
          setCount(count + 1)
        }

        const handleClick2 = () => {
          setCount2(count2 + 1)
        }

        console.log('我是render')
        return (
          <div>
            <p>{count}</p>
            <button onClick={handleClick1}>Click me</button>
            <p>{count2}</p>
            <button onClick={handleClick2}>Click me</button>
          </div>
        )
      }

初始化:

getNum 1
我是render

点击handleClick1:

getNum 2(但是不影响count2值)

我是render

点击handleClick2:

getNum 3(但是不影响count2值)
我是render

 

4.在调用 setState 去更新状态的时候,React 内部会进行类似 Object.is() 这样的浅比较,如果值相等则不会重新渲染

const [count3, setCount3] = React.useState(0)
const [person, setPerson] = React.useState({ name: 'LinDaiDai' })
            <button
              onClick={() => {
                setCount3(0)
              }}
            >
              Click me
            </button>
            <br />
            <button
              onClick={() => {
                setPerson({ name: 'LinDaiDai22' })
                // person.name = 'Gisika';
                // setPerson(person);
                // setPerson({ name: 'LinDaiDai1' })
              }}
            >
              Modify name
            </button>

 

5.简单实现useStatus的demo

      // 1. 初始定义数组和下标
      let _state = []
      let index = 0

      function useMyState(initialState) {
        // 2. 在每次调用 useMyState 的时候,把当前这个 state 的下标缓存起来
        let currentIndex = index
        // 3. 赋值
        _state[currentIndex] =
          _state[currentIndex] === undefined
            ? initialState
            : _state[currentIndex]

        function setState(newState) {
          // 5. 外界更新的时候,由于 setState 和 useMyState 形成了闭包,这里能获取到 currentInex,并成功更新数组中对应下标的值
          _state[currentIndex] = newState
          index = 0
          render()
        }

        // 4. 在调用完一次 useMyState 之后,就要把 index 累加了,方便下一个 state 调用的时候知道自己应该排在哪
        index += 1
        return [_state[currentIndex], setState]
      }
const [count, setCount] = useMyState(0)

 

posted on 2025-04-03 10:27  sss大辉  阅读(24)  评论(0)    收藏  举报

导航