React hooks整理

React hooks整理:

  • 会有 Capture Value 特性
  • 推荐配合 eslint-plugin-react-hooks 使用
  • useEffect:
    • useEffect 依赖一个空数组的时候,会记住 state 的值
    useEffect(()=>{
      setInterval(() => {
        console.log(num)
        setNum(num+1)
      }, 500);
    },[])
    // 一直打印 0,依赖空数组时,这个 effect 会记住 num 的值,每次都是 0
    
    • useEffect 依赖的数组里有值时,每次依赖项更新时,会把更新的值传给 effect 并重新执行 effect 里面的代码
      useEffect(()=>{
        setInterval(() => {
          console.log(num)
          setNum(num+1)
        }, 500);
      },[num])
    
    • useEffect 里面不加 return 时,useEffect 中的代码块相当于在 class 组件的 componentDidMount 和 componentDidUpdate 中的代码块;加了 return 后,return 后的代码块相当于 class 组件里的 componentWillUnmount 中的代码块
      useEffect(()=>{
        const timer = setInterval(() => {
          console.log(num)
          setNum(num+1)
        }, 500);
        return ()=>clearInterval(timer)
      },[num])
    
  • useRef:
    • 代码如下:
    useEffect(()=>{
      countRef.current = count
    },[count])
    useEffect(()=>{
      const timer = setInterval(() => {
        console.log(countRef)
        setCount(countRef.current+1)
      }, 500);
      return ()=>clearInterval(timer)
    },[])
    
    const btnRef = useRef(null)
    useEffect(()=>{
      const handleClick = ()=>{
        setCount(count+1)
      }
      btnRef.current.addEventListener('click',handleClick,false);
      return ()=>{
        btnRef.current.removeEventListener('click', handleClick,false);
      }
    },[count])
    return (
      <div>
        <p>count: {count}</p>
        <button ref={btnRef}>+1</button>
      </div>
    )
    
  • memo: 相当于 pureComponent
// 只传一个参数
import React, {useState, useEffect, useRef, memo} from 'react';
const Child = memo(()=> {
  return (
    <div>
      fffffff
    </div>
  )
})
// 传了两个参数,第二个参数相当于 shouldComponentUpdate
import React, {useState, useEffect, useRef, memo} from 'react';
const Child = memo(()=> {
  return (
    <div>
      fffffff
    </div>
  )
},(prev,next)=>{
  return prev.count === next.count
})
  • useMemo: 缓存的一个值
const Child = memo((props)=> {
  console.log(props)
  const date = new Date()
  return (
    <div>
      当前时间:{date.getHours()}: {date.getMinutes()}: {date.getSeconds()}
    </div>
  )
})
const Parent = ()=> {
  const [count, setCount] = useState(0)
  const [clickTimeCount, setTimeClickCount] = useState(0)
  const timeOption = useMemo(()=>{
    return {
      clickTimeCount
    }
  },[clickTimeCount])
  return (
    <div>
      <div>count: {count}</div>
      <button onClick={()=>{
        setCount(count+1)
      }}>+1</button>
      <button onClick={()=>{
        setTimeClickCount(clickTimeCount+1)
      }}>GET CURRENT TIME</button>
      <Child count={timeOption}/>
    </div>
  )
}
  • useCallback: 缓存的是一个函数
import React, {useState, useEffect, useRef, memo, useMemo, useCallback} from 'react';
const Child = memo((props)=> {
  console.log(props)
  const date = new Date()
  return (
    <div>
      当前时间:{date.getHours()}: {date.getMinutes()}: {date.getSeconds()}
      <input type="text" onChange={props.onChange}/>
    </div>
  )
})
const Parent = ()=> {
  const [count, setCount] = useState(0)
  const [text, setText] = useState('')
  const [clickTimeCount, setTimeClickCount] = useState(0)
  const handleOnchange = useCallback( (e)=>{
    setText(e.target.value)
  },[])

  return (
    <div>
      <div>count: {count}</div>
      <div>text: {text}</div>

      <button onClick={()=>{
        setCount(count+1)
      }}>+1</button>
      <button onClick={()=>{
        setTimeClickCount(clickTimeCount+1)
      }}>GET CURRENT TIME</button>
      <Child count={clickTimeCount} onChange={handleOnchange}/>
    </div>
  )
}
  • 自定义 hooks: 通用逻辑抽离
    • 新建一个 hooks.js 文件,代码如下:
    import {useState,useEffect} from 'react'
    
    export const useWindowSize = () => {
      const [width, setWidth] = useState('0px')
      const [height, setHeight] = useState('0px')
      useEffect(()=>{
        setWidth(document.documentElement.clientWidth+ 'px')
        setHeight(document.documentElement.clientHeight+ 'px')
      },[])
      useEffect(()=>{
        const handleResize = ()=>{
          setWidth(document.documentElement.clientWidth+ 'px')
          setHeight(document.documentElement.clientHeight+ 'px')
        }
        window.addEventListener('resize',handleResize,false)
        return ()=>{
          window.removeEventListener('resize',handleResize,false)
        }
      },[])
      return [width, height]
    }
    
    • 别的组件中引用这个自定义 hooks:
import React, {useState, useEffect, useRef, memo, useMemo, useCallback} from 'react';
import {useWindowSize} from './hooks'
const Parent = ()=> {
  const [width, height] = useWindowSize()
  return (
    <div>
      size:{width} * {height}
    </div>
  )
}

function App() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}
export default App;
  • useReducer、useContext:
import React, {useReducer,useContext} from 'react';

const Ctx = React.createContext(null)
const reducer = (state,action) => {
  switch (action.type) {
    case 'ADD':
      return state + 1
    case 'SUB':
      return state - 1
    default:
      return state
  }
}
const Child = ()=>{
  const [count, dispatch] = useContext(Ctx)
  return (
    <div>
      child: count: {count}
      <button onClick={()=>dispatch({type:'ADD'})}>+1</button>
      <button onClick={()=>dispatch({type:'SUB'})}>-1</button>
    </div>
  )
}
const Parent = ()=> {
  const [count, dispatch] = useContext(Ctx)
  return (
    <div>
      Parent: {count}
      <Child />
    </div>
  )
}

function App() {
  const [count, dispatch] = useReducer(reducer, 20)
  return (
    <Ctx.Provider value={[count, dispatch]}>
      <div className="App">
        <Parent />
      </div>
    </Ctx.Provider>
  );
}
export default App;
  • useSelector(mapStateToProps)、useDispatch(mapDispatchToProps):
import React from 'react'
import {useSelector, useDispatch} from 'react-redux'
import {updateName, updateTel} from './action'
export default ()=>{
  const formData = useSelector(state => {
    console.log(state)
    return state.form
  })
  const dispatch = useDispatch()
  return (
    <div>
      form: <br />
      姓名: <input type='text' onChange={e=>{dispatch(updateName(e.target.value))}} /><br />
      电话: <input type='tel' onChange={e=>{dispatch(updateTel(e.target.value))}} /><br />
    </div>
  )
}

你可能感兴趣的:(react,react)