深入学习React Hook——useState

399 阅读2分钟

本文已参加「新人创作礼」活动,一起开启掘金创作之路。

Hook使用规则

  • 只能在函数的最外层调用Hook,不能在循环、条件判断或子函数中调用。
  • 只能在React函数组件或自定义Hook中调用Hook,不可在其他JavaScript函数中使用。

useState基本用法

const [state,setState] = useState<type>(initialState)

参数

参数类型type

useState右侧的<>部分是typeScript中泛型的用法,用来约束参数initialState的类型。

参数初始值initialState

  • initialState参数可以是具体的值,也可以是函数返回的值。
  • initialState参数只在初始渲染中起作用,后续渲染时会被忽略。

返回值

  • useState的返回值是一个数组,数组第一个元素是state,第二个元素是用来更新state的函数。
  • state和setState变量名可以按需求改变。例如某组件是一个计数器,计时器中保存的state是当前计数的值,那么变量名可以设为counter;而函数名约定为set+变量名(小驼峰)setCounter。

setState

  • setState函数的参数可以是值或更新函数。
  • 如果需要根据原来的state更新state,建议用函数更新!!!如count计时器值+1:setCount(preCount => preCount +1),React保证更新函数的参数始终是最新的state。若用值更新可能会出现异常,如setCount(count+1),因为在异步架构下React不保证执行setCount时拿到的count是最新的。
  • setState函数是稳定的,它不会在组件重新渲染时发生变化。所以不需要在useEffect或useCallback等Hook的依赖列表中添加setState。
  • setState函数不会自动合并更新对象,但可以使用展开运算符来达到合并更新对象的效果。如:setState(preState =>{...preState,...updState})

函数更新与值更新的优劣对比

  • 如果需要原来的state值才能做更新,建议用函数更新。函数更新的优点是可以保证能拿到最新的state;缺点是react不对函数式更新做异步、批量更新优化。
  • 如果不需要原来的state就能做更新,建议用值更新。值更新的优点是react会对值更新做异步、批量更新优化;缺点是在值更新时去取state可能不是最新的。

在一个组件中使用多个state变量

  • 函数组件中可以同时使用多个useState,React依靠Hook调用的顺序识别并使用多个state。
  • React会在单次渲染过程中更新所有待更新的state变量。
  • React官方建议将state切分成多个state变量。

集中式state案例

import React, { memo, useState } from "react"


type Style = {
    color: string,
    background: string
}

const Show: React.FC<{ state: Style }> = (props) => {
    const { color, background } = props.state
    console.log("Show")
    return (
        <div style={{color,background}}>
            测试文字,文字的颜色和背景色可以切换!
        </div>
    )
}

const HandleColor: React.FC<{
    setState: React.Dispatch<React.SetStateAction<Style>>
}> = memo((props) => {
    const { setState } = props
    console.log("HandleColor")
    return (
        <button onClick={() => setState((preState => preState.color === "red" ? { ...preState, color: "blue" }:{ ...preState, color: "red" }))}>点我改变颜色</button>
    )
})

const HandleBackground: React.FC<{
    setState: React.Dispatch<React.SetStateAction<Style>>
}> = memo((props) => {
    const { setState } = props
    console.log("HandleBackground")
    return (
        <button onClick={() => setState((preState => preState.background === "black" ? { ...preState, background: "gray" } : { ...preState, background: "black" }))}>点我改变背景</button>
    )
})

const App = () => { 
    const [state, setState] = useState<Style>({ color: "red",background:"black" })
    console.log("渲染了App")
    return (
        <>
            <Show state={state}/>
            <HandleColor setState={setState}/>
            <HandleBackground setState={setState} />
        </>
    )
}

export default App

点击“在线案例”可以在线看代码的表现。

分散式state案例

import React, { memo, useState } from "react"


const Show: React.FC<{
    color: string,
    background: string
}> = (props) => {
    const { color, background } = props
    console.log("Show")
    return (
        <div style={{color,background}}>
            测试文字,文字的颜色和背景色可以切换!
        </div>
    )
}

const HandleColor: React.FC<{
    setColor: React.Dispatch<React.SetStateAction<string>>
}> = memo((props) => {
    const { setColor } = props
    console.log("HandleColor")
    return (
        <button onClick={()=>setColor((preState=>preState==="red"?"blue":"red"))}>点我改变颜色</button>
    )
})

const HandleBackground: React.FC<{
    setBackground: React.Dispatch<React.SetStateAction<string>>
}> = memo((props) => {
    const { setBackground } = props
    console.log("HandleBackground")
    return (
        <button onClick={()=>setBackground((preState=>preState==="black"?"gray":"black"))}>点我改变背景</button>
    )
})

const App = () => { 
    const [color,setColor]= useState<string>("red")
    const [background, setBackground] = useState<string>("black")
    console.log("渲染了App")
    
    return (
        <>
            <Show color={color} background={background} />
            <HandleColor setColor={setColor}/>
            <HandleBackground setBackground={ setBackground}/>

        </>
    )
}

export default App

点击“在线案例”可以在线看代码的表现。

对比分析

通过集中式state和分散式state代码对比可以看到分散式state代码更易于做组件拆分,可读性和可维护性更好。