React hooks - useState

useState

在hooks出现之前,react的函数式组件也叫做无状态组件(函数里面无法创建属于自己的状态,只能使用props接收)

用法

一个管理状态的 hooks,能让函数组件拥有自己的状态,实现状态的初始化、读取、更新。

特点

  1. 状态变化时,会触发函数组件的重新执行,并根据最新的数据更新渲染 DOM 结构
  2. 以函数的形式为状态赋初始值
  3. 异步变更状态,useState() 返回一个以异步形式变更状态的函数,修改状态后无法立即拿到最新的状态
  4. 结合useEffect监听状态的变化
javascript 复制代码
import React, { useState } from 'react'

export const Count: React.FC = () => {
  const [count, setCount] = useState(0) // 默认初始值undefined,useState只有首次渲染会执行
  // 以函数的形式为状态赋初始值,useState也只会首次渲染执行,更新渲染不执行
  const [date] = useState(() => {
    const dt = new Date()
    return { year: dt.getFullYear(), mouth: dt.getMonth() + 1, day: dt.getDate()}
  })
  useEffect(()=>{
    console.log(count) // 可以监听到最新的值
  },count)
  console.log('组件被重新渲染了') // 每次 count 值发生变化,都会打印
  return (
    <>
      <h1>{count}</h1> <button onClick={() => {
          setCount(count + 1)
          console.log(count) // 打印的还是上一次的值
      }}>+1</button>
      <h2>{date.year}年{date.mouth}月{date.day}日{date.second}秒</h2>
    </>
  )
}

注意事项

  1. 组件rerender时useState不会被重复初始化
  2. 要更新对象类型的值
    须使用展开运算符或 Object.assign()生成新对象覆盖旧对象,才能触发组件的重新渲染
javascript 复制代码
import React, { useState } from 'react'

export const UserInfo: React.FC = () => {
  const [user, setUser] = useState({name: 'zs',age: 12})
  const updateUserInfo = () => {
    // user.name = 'Jesse Pinkman' // 错误使用:因为set 函数内部,会对更新前后的值进行对比,不会触发组件的重新渲染
    // 解决方案:用新对象的引用替换旧对象的引用,即可正常触发组件的重新渲染
    // setUser({ ...user })
    // setUser(Object.assign({}, user))
    setUser({ ...user, name: 'Jesse Pinkman' })
  }

  return (
    <>
      <h1>用户信息:</h1>
      <p>姓名:{user.name}</p>
      <p>年龄:{user.age}</p>
      <button onClick={updateUserInfo}>更新用户信息</button>
    </>
  )
}
  1. 值异步更新
    连续多次以相同的操作更新状态值时,React 内部会对传递过来的新值进行比较,值相同,则会屏蔽后续的更新行为,从而防止组件频繁渲染的问题。
    当修改state状态时,如果新值依赖于旧值(基于旧值计算得到新值)时,不要直接在外部计算,通过函数的形参拿到旧值并计算最终return新值。
javascript 复制代码
export const Count: React.FC = () => {
  const [count, setCount] = useState(() => 0)

  const add = () => {
    setCount(count + 1) // 两次操作后count值任然为1
    setCount(count + 1)
  }
  const addPrev = () => {
    setCount((c) => c + 1) // 传递了更新状态的函数进去,两次操作后count值为2
    setCount((c) => c + 1)
  }

  return (
    <>
      <h1>当前的 count 值为:{count}</h1>
      <button onClick={add}>+1</button>
      <button onClick={addPrev}>+1</button>
    </>
  )
} 
  1. 模拟组件的强制刷新
    useState 的状态发生了变化,就会触发函数组件的重新渲染,从而达到强制刷新的目的
javascript 复制代码
import React, { useState } from 'react'

export const FUpdate: React.FC = () => {
  const [, forceUpdate] = useState({})
  // 每次都会给 forceUpdate 传递一个新对象,从而触发组件的重新渲染
  const onRefresh = () => forceUpdate({})
  return (
    <>
      <button onClick={onRefresh}>点击强制刷新 --- {Date.now()}</button>
    </>
  )
}
相关推荐
葬送的代码人生5 小时前
React组件化哲学:如何优雅地"变秃也变强"
前端·javascript·react.js
小马虎本人5 小时前
如果接口返回的数据特别慢?要怎么办?难道就要在当前页面一直等吗
前端·react.js·aigc
多啦C梦a5 小时前
从 React 初体验到数据驱动的界面开发:一步步解析 Todo List 组件
javascript·react.js
程序员小刘5 小时前
如何优化React Native应用以适配HarmonyOS5?
javascript·react native·react.js·华为·harmonyos
海盐泡泡龟8 小时前
“组件、路由懒加载”,在 Vue3 和 React 中分别如何实现? (copy)
前端·javascript·react.js
国家不保护废物10 小时前
🧩 React 组件化进阶:像乐高大师一样搭建你的应用世界!
前端·react.js·ai编程
TimelessHaze10 小时前
从"切图崽"到前端工程师:React 到底是个啥?🚀
前端·react.js·ai编程
聪明的水跃鱼10 小时前
闲谈 React 渲染机制
react.js
Java陈序员10 小时前
再见 Navicat!一款开源的 Web 数据库管理工具!
java·react.js·docker
HarderCoder10 小时前
ByAI:Rect-redux实现及connect函数
前端·react.js