Fork me on GitHub

React hooks 之 useState

一、useState的介绍

useState是react自带的一个hook函数,它的作用是用来声明状态变量

声明的方式

const [ count , setCount ] = useState(0)

注意:这是数组的解构赋值的方式,如果不用解构赋值,则:

let _useState = useState(0)
let count = _useState[0]
let setCount = _useState[1]

例子:

import React, { useState } from 'react'
//点击按钮,对点击次数计数
//函数组建的方法 export default function App() { const [ count , setCount ] = useState(0) return ( <div> You clicked {count} times. <button onClick={()=>{setCount(count+1)}}>click me</button> </div> ) }

同样的功能相较于函数组件,类组件则更加繁琐:需要绑定this

import React, { Component } from 'react'
//点击按钮,对点击次数计数 //类组件的方法 export default class App extends Component { constructor(props){ super(props) this.state = { count : 0 } } render() { return ( <div> You clicked {this.state.count} times. <button onClick={this.addCoount.bind(this)}>click me</button> </div> ) } addCoount(){ this.setState({count:this.state.count+1}) } }

二、多状态声明及注意事项

多状态声明:

import React, {useState} from 'react'
// useState多状态声明
export default function App() {
    const [ age, setAge ] = useState(24)
    const [ sex, setSex ] = useState('男')
    const [ job, setjob ] = useState('前端工程师')
    return (
        <div>
            <p>spikezz今年{age}岁</p>
            <p>性别:{sex}</p>
            <p>工作是{job}</p>
        </div>
    )
}

这里在使用useState的时候只赋了初始值,并没有绑定任何的key,那么react是怎么保证这三个useState找到它自己对应的state呢

其实,react是根据useState出现的顺序来确定的。

我们可以加个判断语句试试

import React, {useState} from 'react'
// useState多状态声明时,加入条件语句
let flag = true
export default function App() {
    const [ age, setAge ] = useState(24)
    if(flag){
        const [ sex, setSex ] = useState('男')
        flag = false
    }
    const [ job, setjob ] = useState('前端工程师')
    return (
        <div>
            <p>spikezz今年{age}岁</p>
            <p>性别:{sex}</p>
            <p>工作是{job}</p>
        </div>
    )
}

可以看到的是,程序直接报错

React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render

即:React Hook “useState”被有条件地调用。在每个组件渲染中,必须以完全相同的顺序调用React Hooks

 三、使用细节

1、useState尽量写在函数组件的开始部分,以方便阅读

2、useState不要写在循环体或者判断语句里

3、useState返回的第二个值(setXxx)引用是不变的,目的是节约内存空间

4、使用第二个返回值函数(setXxx)改变数据,如果新的数据和旧的数据是完全一样的(Object.is比较),那么组件不会重新渲染

5、使用第二个返回值函数(setXxx)改变函数,如果新旧数据不一样,新数据会直接替换旧数据,而不会合并

6、如果要实现强制刷新组件:

  类组件:this.forceUpdate()

  函数组件:给setXxx函数传入一个空对象

7、如果某些组件之间没有必然的联系,那么尽量写成多个状态的形式,不要合并成一个对象

8、和类组件的改变状态一样,函数组件改变状态时也是异步的(dom事件中改变状态),那么此时就会将多次改变状态合并在一起最终变化,提高效率。

此时不能信任新的值,而是应该使用回调函数的形式(即以下代码的注释部分)

import React, { useState, useEffect } from 'react';
// 点击按钮,对点击次数计数
// 函数组件
function App() {
    const [count, setCount] = useState(0);
    useEffect(() => {
        console.log(`useEffect=>You clicked ${count} times`)
    })
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => {
                // 可以观察到的是,两次setCount只会有执行一次的效果
                // 因为在Dom中状态的改变是异步的,就会将多个状态改变合并在一起
                setCount(count + 1)
                setCount(count + 1)
                // 通过回调函数修改的话可以执行成功
                // setCount(count => count+1)
                // setCount(count => count+1)
            }}>click me</button>
        </div>
    )
}
export default App;
posted @ 2021-05-07 17:51  spikezz  阅读(419)  评论(0)    收藏  举报
1