• React中useState的用法
  • 发布于 2个月前
  • 183 热度
    0 评论
前言

了解一个框架的最好方式,便是从它的数据开始,无论是vue,亦或者react,都是如此。对于react来说,最重要的数据莫过于状态值state,在官方的新文档中,state被描述为一个组件的记忆,我们可以将其理解为显示在屏幕上的动态数据。


为什么需要状态
如果没有状态,react的组件将会是这样的:
export default function Count(){
    let num = 0
    
    const handleClick = () => {
        num += 1
    }
    
    return (
        <>
            <div>Count: { num }</div>
            <button onClick={ handleClick }>+1</button>
        </>
    )
} 
handleClick() 事件处理函数更新了局部变量 num。但存在两个原因使得屏幕上的num不会发生变化:
1.局部变量无法在多次渲染中持久保存。  当 React 再次渲染这个组件时,它会从头开始渲染——不会考虑之前对局部变量的任何更改。
2.更改局部变量不会触发渲染。  React 没有意识到它需要使用新数据再次渲染组件。

要使用新数据更新组件,需要做两件事:
1.保留 渲染之间的数据。
2.触发 React 使用新数据渲染组件(重新渲染)。

useState 介绍
现在我们用useState来新增一个状态:
const [state, setState] = useState(initialState);
其中state变量用于保存渲染间的数据,而setState函数则用来更新变量并触发 React 再次渲染组件(即re-render),re-render会再次调用组件函数,并用新状态值替换旧的状态值去执行相应的渲染或操作,我们将 Count 组件用状态改写如下:
export default function Count(){
    const [ num, setNum ] = useState(0)
    // 堆代码 duidaima.com
    const handleClick = () => {
        setNum(num + 1)
    }
    
    return (
        <>
            <div>Count: { num }</div>
            <button onClick={ handleClick }>+1</button>
        </>
    )
} 

现在屏幕上的num就能实现动态变化了。


状态的不可变性
从useState的使用形式上看,不知道会不会有人有这样的疑问,我们能不能用let去声明变量?能不能不使用解构赋值?比如写成这样:
let [state, setState] = useState(initialState);
或者这样:
const stateArr = useState(initialState);

react并没有严格限制这些写法,但是它们都是不规范的写法,这里就不得不谈及状态的不可变性了。在react的每一次组件渲染切片中,其内部的状态值在其渲染到屏幕上之前的那一刻,就已经固定下来了,后续无论什么样的操作,我们都不应该再对其造成影响,为什么要这么做呢?我们知道动画是由一帧帧快照组成的,react也是如此,在react中,每一次渲染就如同一帧快照切片,这样的每一帧快照,它的状态就必须自始至终保持不变,以便我们可以随时进行Time Travel,也不会出现前后渲染不一致的问题。


因此,以上的两种不规范的写法,都比较容易导致state和setState被重新赋值,在不知不觉中打破状态的不可变性原则,我们在日常开发中要注意避免此类写法,遵守react的开发规范,才能尽量减少开发过程中的一些错误。
这里列举一种常见的不规范的写法:
const [state, setState] = useState([
    { a: 0 },
    { b: 1 }
]);
// 堆代码 duidaima.com
// 不规范写法
const s = [...state]
s[0].a = -1
setState(s)

// 规范写法
const s = [...state]
s[0] = { ...s[0], a: -1 }
setState(s)

维持状态不可变性的最好方法便是拷贝,如何以最低的成本去进行拷贝,需要我们自己去衡量把握。


总结
useState是用来创建一个新状态的Hook,它让react拥有了动态更新视图的能力,并且具有一定的规范性,只要我们遵守其开发规范,就能减少在开发过程中遇到的许多问题。

用户评论