React Hooks小记(一)_useState

useState

1. 基本用法

useState,能让函数组件拥有自己的状态,因此,它是一个管理状态的 hooks API。通过 useState 可以实现状态的初始化、读取、更新。

基本语法格式如下:

const [状态名, set函数] = useState(初始值)

其中:状态名所代表的数据,可以被函数组件使用;如果要修改状态名所代表的数据,需要调用 set 函数 进行修改。例如:

import { useState } from 'react' 
export function Count() { 
    // 定义状态 count,其初始值为 0 
    // 如果要修改 count 的值,需要调用 setCount(新值) 函数 
    const [count, setCount] = useState(0) 
    
    return ( 
        <> 
            <!-- 在函数组件内,使用名为 count 的状态 --> 
            <h1>当前的 count 值为:{count}</h1> 
            <!-- 点击按钮时,调用 setCount() 函数,为 count 赋新值 --> 
            <button onClick={() => setCount(count + 1)}>点我+1</button> 
		</> 
	) 
}

2. 状态变化时,会触发函数组件的重新执行

在函数组件中使用 setState 定义状态之后,每当状态发生变化,都会触发函数组件的重新执行,从而根据最新的数据更新渲染 DOM 结构。

例如:

import { useState } from 'react' 
export function Count() { 
    // 定义状态 count,其初始值为 0 
    // 如果要修改 count 的值,需要调用 setCount(新值) 函数 
    const [count, setCount] = useState(0) 
    // 每次 count 值发生变化,都会打印下面的这句话: 
    console.log('组件被重新渲染了') 
    const add = () => { setCount(count + 1) } 
    return ( 
        <> 
            <!-- 在函数组件内,使用名为 count 的状态 --> 
            <h1>当前的 count 值为:{count}</h1> 
            <!-- 点击按钮时,在 add 处理函数中,调用 setCount() 函数,为 count 赋新值 --> 
            <button onClick={add}>+1</button> 
		</> 
	) 
}

注意:当函数式组件被重新执行时,不会重复调用 useState() 给数据赋初值,而是会复用上次的 state 值。

3. 以【函数】形式为状态赋初始值

在使用 useState 定义状态时,除了可以直接给定初始值,还可以通过函数返回值的形式,为状态赋初始值,语法格式如下:

const [value, setValue] = useState(() => 初始值)

例如:

export const DateCom: React.FC = () => { 
    // const [date] = useState({ year: 2023, month: 9, day: 11 }) 
    const [date, setDate] = useState(() => { 
        const dt = new Date() 
        return { 
            year: dt.getFullYear(), 
            month: dt.getMonth() + 1, 
            day: dt.getDate() 
        } 
    }) 
    
    return ( 
        <> 
        	<h1>今日信息:</h1> 
        	<p>年份:{date.year}</p> 
			<p>月份:{date.month}</p> 
			<p>日期:{date.day}</p> 
		</> 
	) 
}

注意:以函数的形式为状态赋初始值时,只有组件首次被渲染才会执行 fn 函数;当组件被更新时,会以更新前的值作为状态的初始值,赋初始值的函数不会执行。

4. useState 是异步变更状态的

调用 useState() 会返回一个变更状态的函数,这个函数内部是以异步的形式修改状态的,所以修改状态后无法立即拿到最新的状态,例如:

export const Count: React.FC = () => { 
    const [count, setCount] = useState(() => 0) 
    const add = () => { 
        // 1. 让数值自增+1 setCount(count + 1) 
        // 2. 打印 count 的值 console.log(count) } 
        return ( 
            <> 
            	<h1>当前的 count 值为:{count}</h1> 
    			<button onClick={add}>+1</button> 
    		</> 
    ) 
}

在上述代码的第8行,打印出来的 count 值是更新前的旧值,而非更新后的新值。证明 useState 是异步变更状态的。

5. 结合 useEffect 监听状态的变化

为了能够监听到状态的变化,react 提供了 useEffect 函数。它能够监听依赖项状态的变化,并执行对应的回调函数。基本语法格式如下:

useEffect(() => { /* 依赖项变化时,要触发的回调函数 */ }, [依赖项])

例如:

export const Count: React.FC = () => { 
    const [count, setCount] = useState(() => 0) 
    const add = () => { setCount(count + 1) } 
    // 当 count 变化后,会触发 useEffect 指定的回调函数 
    useEffect(() => { 
        console.log(count) 
    }, [count]) 
    return ( 
        <> 
        	<h1>当前的 count 值为:{count}</h1> 
			<button onClick={add}>+1</button> 
		</> 
	) 
}

注意:useEffect 也是 React 提供的 Hooks API,后面的课程中会对它进行详细的介绍。

6. 注意事项

6.1 更新对象/数组类型的值

知识回顾:判断对象的值是否改变,看的是地址是否改变

如果要更新对象类型的值,并触发组件的重新渲染,则必须使用展开运算符Object.assign() 生成一个新对象,用新对象覆盖旧对象,才能正常触发组件的重新渲染。

示例代码如下:

export const UserInfo: React.FC = () => { 
    const [user, setUser] = useState({ 
        name: 'zs', 
        age: 12, 
        gender: '男' 
    }) 
    
    const updateUserInfo = () => { 
        user.name = 'Jesse Pinkman' 
        // 下面的写法是错误的,因为 set 函数内部,会对更新前后的值进行对比; 
        // 由于更新前后的 user,原值的引用和新值的引用相同, 
        // 所以 react 认为值没有发生变化,不会触发组件的重新渲染。 
        // setUser(user) 
        
        // 【解决方案】:用新对象的引用替换旧对象的引用,即可正常触发组件的重新渲染。 
        // 1、setUser({ ...user }) 
        // 2、setUser(Object.assign({}, user)) 
        
        // 通常在实际开发中,经常结合【展开运算符 + 属性值覆盖】的形式更新对象的属性值: 
        setUser({...user, name: 'Jesse Pinkman'}) } 
    return ( 
        <> 
        	<h1>用户信息:</h1> 
        	<p>姓名:{user.name}</p> 
			<p>年龄:{user.age}</p> 
			<p>性别:{user.gender}</p> 
			<button onClick={updateUserInfo}>更新用户信息</button> 
		</> 
	) 
}

6.2 解决值更新不及时的 Bug

当连续多次以相同的操作更新状态值时,React 内部会对传递过来的新值进行比较,如果值相同,则会屏蔽后续的更新行为,从而防止组件频繁渲染的问题。这虽然提高了性能,但也带来了一个使用误区,例如:

export const Count: React.FC = () => { 
    const [count, setCount] = useState(() => 0) 
    const add = () => { 
        // 1. 希望让 count 值从 0 自增到 1 
        setCount(count + 1) 
        // 2. 希望让 count 值从 1 自增到 2 
        setCount(count + 1) 
    } 
    return ( 
        <> 
        	<h1>当前的 count 值为:{count}</h1> 
			<button onClick={add}>+1</button> 
		</> 
	) 
}

经过测试,我们发现上述代码执行的结果,只是让 count 从 0 变成了 1,最终的 count 值并不是 2。Why?

因为 setCount 是异步地更新状态值的,所以前后两次调用 setCount 传递进去的新值都是 1 。React 内部如果遇到两次相同的状态,则会默认阻止组件再次更新。

为了解决上述的问题,我们可以使用函数的方式给状态赋新值。当函数执行时才通过函数的形参,拿到当前的状态值,并基于它返回新的状态值。

示例代码如下:

export const Count: React.FC = () => { 
    const [count, setCount] = useState(() => 0) 
    const add = () => { 
        // 传递了更新状态的函数进去 
        setCount((c) => c + 1) 
        setCount((c) => c + 1) } 
    return ( 
        <> 
        	<h1>当前的 count 值为:{count}</h1> 
			<button onClick={add}>+1</button> 
		</> 
	) 
}

【总结】setState 更新值的两种方式

​ 1、setCount(新值)

​ 2、setCount((pre) => 基于pre计算并返回的新值)

tips:当我们修改 state 时,如果新值依赖旧值,应选择第二种方式更新状态

6.3 使用 setState 模拟组件的强制刷新

在函数组件中,我们可以通过 useState模拟 forceUpdate 的强制刷新操作。因为只要 useState 的状态发生了变化,就会触发函数组件的重新渲染,从而达到强制刷新的目的。具体的代码示例如下:

export const FUpdate: React.FC = () => { 
    const [, forceUpdate] = useState({}) 
    // 每次调用 onRefresh 函数,都会给 forceUpdate 传递一个新对象 
    // 从而触发组件的重新渲染 
    const onRefresh = () => forceUpdate({}) 
    return ( 
        <> 
        	<button onClick={onRefresh}>点击强制刷新 --- {Date.now()}</button> 
		</> 
	) 
}

注意:因为每次传入的对象的地址不同,所以一定会使组件刷新。

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: React Hooks useState是React中的一个钩子函数,用于在函数组件中使用状态。它接受一个初始状态值作为参数,并返回一个数组,其中第一个元素是当前状态值,第二个元素是一个函数,用于更新状态值。使用useState可以避免使用类组件时需要使用this.setState来更新状态的繁琐操作,使代码更加简洁易懂。 ### 回答2: React HooksReact16.8版本之后推出的新特性,其目的是为了方便函数组件的代码编写,从而更加灵活和高效。而useState是React Hooks中最常用的一种钩子,它用于设置和修改组件的状态。 简单来说,useState就是一个解决方案,能够让函数组件拥有与class组件类似的状态管理功能。通过将useState钩子引入函数组件中,我们可以方便的定义并修改组件状态,而无需设置构造函数和this关键字。同时,useState还可以返回一个数组,包含两个值。第一个值是当前状态的值,第二个值是修改状态的函数。当调用修改状态的函数时,React会重新渲染组件,并将新状态传递给函数。 除此之外,useState还有一些特殊的用法。比如,我们可以为useState设置默认值,这样在初始渲染时就可以使用了。同时,我们也可以为useState设置回调函数,以处理更加高阶的状态管理。除此之外,useState还可以配合其他React Hooks使用,比如useEffect等等。 总的来说,useState是React Hooks中非常重要的一种钩子。它的出现简化了函数组件的状态管理,让我们能够更加专注于业务逻辑的编写。同时,useState还十分灵活和高效,能够为我们带来更加完整的编程体验。 ### 回答3: React HooksReact 16.8 版本中引入的一种新特性,它可以让我们在函数组件中使用 state 和其他 React 特性。其中最常用的一个 Hook 就是 useState。 useState 的作用是在函数组件中声明一个 state 变量,并且返回一个包含 state 和更新 state 的函数的数组。 例如,我们可以在一个计数器组件中使用 useState: ``` import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <div> <p>You clicked {count} times</p> <button onClick={handleClick}> Click me </button> </div> ); } ``` 在这个例子中,useState 的第一个参数是状态的初始值,这里是 0。useState 返回的数组的第一个元素是当前的状态值 count,第二个元素是更新状态值的函数 setCount。我们可以在 handleClick 函数中调用 setCount 来更新 count 的值。 useState Hook 还有一些有用的特性,例如它可以接收一个函数作为初始状态的值。这个函数会在组件渲染时调用,而且它只会调用一次。这个特性可以用来避免在函数组件中使用类组件中的 this.state。 useState 还可以用来处理复杂的 state,例如对象或数组。我们可以使用 ES6 的扩展运算符来保持对象或数组的不可变性: ``` const [person, setPerson] = useState({ name: '', age: 0 }) function handleChangeName(event) { setPerson({ ...person, name: event.target.value }); } function handleChangeAge(event) { setPerson({ ...person, age: event.target.value }); } ``` 在这个例子中,我们使用 useState 声明了一个包含 name 和 age 属性的 person 对象。在 handleChangeName 和 handleChangeAge 函数中,我们使用扩展运算符保持对象的不可变性,而且我们只更新对象的一个属性。这种做法比直接调用 setPerson 更高效,因为我们只更新了一个属性,而不是整个对象。 总之,useState Hook 是 React 中的一个非常有用的函数,它让我们可以在函数组件中使用类组件中的 state 并且让我们更轻松地处理复杂的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值