useState

useState来自react,他有两个参数

  1. 参数一:当前状态的值(第一调为初始化值)
  2. 参数二:设置状态值的函数
import React, { useState } from 'react';

export default function Counter2() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h2>当前计数: {count}</h2>
      <button onClick={e => setCount(count + 1)}>+1</button>
      <button onClick={e => setCount(count - 1)}>-1</button>
    </div>
  )
}

这里点击button按钮后,会完成两件事情:

  1. 调用setCount,设置一个新的值;
  2. 组件重新渲染,并且根据新的值返回DOM结构;

useState是异步函数还是同步函数

答案是异步函数
有没有办法让useState变成同步函数呢?答案是有的
我们可以自定义一个hooks,将useState变成同步。

import { useEffect, useState, useCallback } from 'react'

const useSyncCallback = callback => {
    const [proxyState, setProxyState] = useState({ current: false })

    const Func = useCallback(() => {
        setProxyState({ current: true })
    }, [proxyState])

    useEffect(() => {
        if (proxyState.current === true) setProxyState({ current: false })
    }, [proxyState])

    useEffect(() => {
        proxyState.current && callback()
    })

    return Func
}

export default useSyncCallback

首先,在useSyncCallback中创建一个标示proxyState,初始的时候会把proxyState的current值赋成false,在callback执行之前会先判断current是否为true,如果为true就允许callback执行,若果为false,就跳过不执行,因为useEffect在组件render之后,只要依赖项有变化就会执行,所以我们无法掌控我们的函数执行,在useSyncCallback中创建一个新的函数Func,并返回,通过这个Func来模拟函数调用,

在这个函数中我们要做的就是变更prxoyState的current值为true,来使得让callback被调用的条件成立,同时触发react组件render这样内部的useEffect就会执行,随后调用callback实现我们想要的效果。

Effect Hook

Effect Hook 可以让你来完成一些类似于class中生命周期的功能;
useEffect要求我们传入一个回调函数,在React执行完更新DOM操作之后,就会回调这个函数;
默认情况下,无论是第一次渲染之后,还是每次更新之后,都会执行这个 回调函数;
useEffect传入的回调函数A本身可以有一个返回值,这个返回值是另外一个回调函数B:

import React, { useState, useEffect } from 'react';

export default function EffectHookClear() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `当前计数: ${count}`;
    console.log("每次DOM更新时会回调");

    return () => {
      console.log("DOM被移除时会回调");
    }
  })

  return (
    <div>
      <h2>当前计数: {count}</h2>
      <button onClick={e => setCount(count + 1)}>+1</button>
      <button onClick={e => setCount(count - 1)}>-1</button>
    </div>
  )
}

useEffect实际上有两个参数:

  1. 参数一:执行的回调函数
  2. 参数二:该useEffect执行的依赖,哪些State发生改变时才重新执行(受谁的影响)
    来看案例
import React, { useState, useEffect } from 'react';

export default function EffectPerformance() {
  const [count, setCount] = useState(0);
  const [show, setShow] = useState(true);

  useEffect(() => {
    console.log("修改DOM");
  }, [count])

  return (
    <div>
      <h2>当前计数: {count}</h2>
      <button onClick={e => setCount(count + 1)}>+1</button>
      <button onClick={e => setShow(!show)}>切换</button>
    </div>
  )
}


在这个案例中,我们修改show的值,是不会让useEffect重新被执行的;因为useEffect第二个依赖项里面没有show的值。

Q.E.D.