useEffect运用

207 阅读1分钟

一个计时器,直接看代码

import * as React from 'react'

const {useEffect, useState } = React

const Counter:React.FC<{}> = () => {
  const [count, setCount] = useState(0)
  const step = 1
  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count + step)//所以count只会改变一次,由0=>1
    },1000)
    return () => {
      clearInterval(timer)
    };
  }, [])//因为useEffect(callback,[])只在dom渲染完成之后会执行一次callback
  return (
    <>
      <div>{count}</div>
    </>
  )
}

export default Counter

useEffect(callback,[]),因为callback仅会在dom渲染完成之后执行一次,后续任何state发生变化,callback都不会执行,所以setCount(count + step) //count 由 0=>1后不会发生变化。 为了达到count每秒都递增step的需求,可以调整为setCount(curCount => curCount+step)

而若step也是动态的呢?则可以用useReducer实现:

import * as React from 'react'
import { Button } from 'antd';

const {useEffect,useReducer } = React

export interface IState {
  count:number,
  step:number
}

export interface IAction {
  type:string
  payload?:any
}

export interface IState {
  count:number
  step:number
}


const reducer = <T extends IState>(state:T, action:IAction):T =>  {
  const {count,step} = state
  switch (action.type){
    case 'TICK':
      return {...state,count:count+step}
    case 'INCREASESTEP':
      return {...state,step:step+1}
    case 'DECREASESTEP':
      return {...state,step:step-1}
    default:
      return state
  }
     

}

const UseEffect:React.FC<{}> = () => {

  const initState:IState = {
    count:0,
    step:1
  }

   

  const [state,dispatch] = useReducer(reducer, initState)

  useEffect(() => {
    const timer = setInterval(() => {
      dispatch({type:'TICK'})
    },1000)
    return () => {clearInterval(timer)}
  },[])
  const {increaseStep,decreaseStep} = React.useMemo(() => {
    return (
      {
        increaseStep:() => {
          dispatch({type:'INCREASESTEP'})
        },
        decreaseStep:() => {
          dispatch({type:'DECREASESTEP'})
        }
      }
    )
  },[])

 
  return (
    <div>
      <div>Step:{state.step}</div>
      <div>Count:{state.count}</div>
      <Button onClick={increaseStep}>Change Step +</Button>    
      <Button onClick={decreaseStep}>Change Step -</Button>    
    </div>
  )
}

export default UseEffect