React Hook

作者: 二荣xxx | 来源:发表于2022-02-28 23:26 被阅读0次

    Hook 是能让你在函数组件中“钩入” React 特性的函数(hook是react16.8的新增特性,让函数组件可以使用state以及其他react特性)

    一、useState

    useState用来创建state变量

    const [state,setState]=React.useState(0)
    const [state,setState]=React.useState({name:'frank',age:'18})
    // 0或{name:'frank'}为state的初始值,setState函数可以改变state的值
    
    setState(2)
    setState({...state,name:'newName'})
    // 由于react更新是重新生成一个新对象,react只会生成传入的对象,所以如果不想另一个属性遗失就必须使用将原本的对象展开放上去
    

    二、useReducer

    useReducer是useState的综合版
    useReducer接受两个参数,一个操作函数,一个初始值

    const [state,dispatch]=React.useReducer(fn,obj)
    // 调用
    dispatch({type:'name'}) //参数传给fn的action
    

    函数

    const fn =(state,action)=>{
    // state为原始state;action为传过来的参数
    return 新state(obj)的值
    }
    

    初始值

    const obj={
      name:'frank',
      age:'18'
    }
    

    三、useContext

    useContext上下文,上下文是局部(context.provider包裹)的全局变量

    // 创建上下文
    const Context = React.createContext(null)
    
    // 使用context.provider圈定作用域
    <Context.Provider value={{ n, setN }}>
       app
       <Father />
    </Context.Provider>
    
    // 使用context传过来的值
    const Father = () => {
      const { n, setN } = useContext(Context) // 使用上下文的值
      const onButton = () => {
        setN(n + 1)
      }
      return (
        <div>
          father:{n}
         <button onClick={onButton}>+1</button>
        </div>
      )
    }
    

    注意:这个地方更改n的值界面也随之更改,并不是因为react的响应式,而是因为每次调用setN都会重新渲染App,发现n的值变了界面才变

    四、useEffect

    useEffect 使用副作用,名字取得不是很好理解,平替的名字可以是afterRender(渲染之后执行),

    // 以下三个都会在第一次渲染执行一次
    useEffect(() => {}) //任何元素变化都执行
    useEffect(() => {},[n]) //n变化执行
    useEffect(() => {},[])  //挂载执行
    useEffect(() => {
        return ()=>{}  //消亡执行
    },[]) 
    

    通常情况下useEffect都是由上往下执行,但是useLayoutEffect在它之前执行

    useLayoutEffect

    useLayoutEffect是在Dom创建之后,渲染之前执行。原理如下:


    useLayoutEffect.png

    五、memo、useMemo、和useCallback

    这三个api都是为了防多次渲染而来的
    举个栗子,以下代码中m的值没有变,但是Child还是执行了。。怎么防止这种情况呢?

    const App = () => {
      const [n, setN] = useState(0)
      const [m, setM] = useState('a')
      return (
        <div>
          <div>grandfather</div>
          <button onClick={() => { setN(i => i + 1) }}>+1</button>
          <Father n={n} />
          <Child m={m} />
        </div>
      )
    }
    
    const Father = (props) => {
      console.log('father执行了')
      return (
        <div>father:{props.n}</div>
      )
    }
    
    const Child = (props) => {
        console.log('child执行了')
        return (
            <div>child:{props.m}</div>
        )
      }
    
    • 将组件传给React.memo
    const Child2 = React.memo(Child) //将Child2代替Child使用
    // 或 
    const Child = memo(
    () => {
        return (
            <div>child:{props.m}</div>
        )
      }
    )
    

    只是这么做有一个bug,那就是当props传递的是函数时,这个方法不生效。这时就要用到useMemo了

    // 假如以下是传递的函数
    const fn=React.useMemo(()=>{return ()=>{}},[m]) //当n变化时被传的组件才会执行
    

    只是这么写是不是看着有点怪怪的。于是react提供了个语法糖,可以直接传个函数React.useCallback(fn,value)

    const fn1 = React.useCallback(()=>{},[m])
    

    其实这就有点类似于vue的computed了,有缓存当依赖的值变化才执行

    六、useRef

    useRef声明一个不变的值(这里说的不变是指内存地址不变)

    // 声明
    const count = useRef(0)
    // 使用
    count.current += 1
    

    因为更改useRef的值不会导致app渲染,会造成结果变了UI没更新。解决:

    const [n, setn] = useState(0)
    // 调用一下
    setn()
    

    使用useState的特性重新(手动)render一下App

    相关文章

      网友评论

        本文标题:React Hook

        本文链接:https://www.haomeiwen.com/subject/rarrlrtx.html