2

About Hooks

Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则:
  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。

useState

1. 形式
import React,{useState} from 'React'
let [num,setNum]=useState(0)

useState接收一个参数作为初始值,返回一个数组。

  • 数组第一项是状态值
  • 数组第二项是改变状态值的函数
2. 使用方法
<button onClick={()=>{setNum(n+1)}}>+1</button>
3. 多项状态值使用useState注意事项
let [a,setA] = useState(0)
let [b,setB] = useState('B')
let [c,setC] = useState(1)
    • 没有声明key,那么如何将useState和每个状态值对应起来呢?
    • React是根据多个useState的声明顺序来确定useState对应的状态值的。换句话说,在进行调用useState()API时,一定不能使用判断语句等可能改变其顺序的逻辑,否则会报错。
    1. 对象类型不支持局部更新
      如果state是一个对象,setState不会帮助我们局部更新state。正确的方式是setState({...state, n: 1})
    2. setState接受函数
      setState(i=>i+1)

    useEffect

    1. 形式
    useEffect(() => {
        doSomething
      },[]);
    • 参数

      • 第一个参数接收一个函数,在对应的生命周期执行。
      • 第二个参数接受一个数组,当数组中的状态值发生变化时调用 useEffect 。
    • 返回值:返回一个函数,React 将会在执行清除操作时调用它。
    2. 原理说明

    useEffect 在第一次渲染之后每次更新之后都会执行(在渲染之前执行可以使用useLayoutEffect)。你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载 mount”还是“更新 update”。

    3. 对比class
    //挂载(第一次渲染
    componentDidMount  =>  useEffect(()=>{...},[])
    //更新
    componentDidUpdate  =>  useEffect(()=>{...},[props])
    //清理
    componentWillUnmount =>   useEffect(()=>{ return()=>{ console.log('cleanUp') } })

    useMemo、useCallback、React.memo

    参考:https://juejin.cn/post/684490...

    使用方法:
    const App = () => {
        const handleClick = useCallback(()=> console.log('click'),[])   //防止每次memo对比时,props(杉树声明)都发生了浅层改变导致的多余渲染
        let user = useMemo(()=>({ name: 'oliver' }),[]) //防止每次memo对比时,props(对象字面量)都发生了浅层改变导致的多余渲染
        return (
            <Child onClick={handleClick} user={user} />
        )
    }
    
    const Child = React.memo((props)=>{
        return (
            <button onClick={props.handleClick}>child</button>
        )
    })
    额外说明:
    useMemo(()=>fn,[...depds]) 
    //等价于
    useCallbacl(fn,[...depds])
    总结:

    不要盲目使用这些hooks进行性能优化

    1. 在子组件不需要父组件的值和函数的情况下,只需要使用memo函数包裹子组件即可。
    2. 在使用函数的情况,需要考虑有没有函数传递给子组件使用useCallback。
    3. 在值有所依赖的项,并且是对象和数组等值的时候而使用useMemo(当返回的是原始数据类型如字符串、数字、布尔值,就不要使用useMemo了)。

    Oliver
    76 声望13 粉丝

    Slow Done, Achieve More.