react最常用的hooks有,useState,useEffect,useMemo,useCallback

首先我们来先聊useState,设置和改变state,代替原来的state和setState


import  { useState } from "react";
import './index.css'

export default () => {
    const [ count, setCount ] = useState(0);   
    const handleClick = ()=>{
        console.log(count)//0
        setCount(count + 1);
    }
    return (
        <div className='container'>
            <h3> 计算结果: {count} </h3>
            <button onClick={()=>handleClick()}>每次加一</button>
        </div>
    );
};

setState的‘异步’并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形成了所谓的‘异步’(有一个变量isBatchingUpdates和batchedUpdates来处理这个问题)

useEffect 代替原来的生命周期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合并版

useEffect可以多次使用,按照先后顺序执行
useLayoutEffect强制useeffect的执行为同步,并且先执行useLayoutEffect内部的函数

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

 

//箭头函数的写法,改变状态

const UseEffect = (props) => {

    //创建了一个叫hook的变量,sethook方法可以改变这个变量,初始值为‘react hook 是真的好用啊’

    const [ hook, sethook ] = useState('react hook 是真的好用啊');

    const [ name ] = useState('baby张');

    return (

        <header className="UseEffect-header">

            <h3>UseEffect</h3>

            <Child hook={hook} name={name} />

            {/**上面的变量和下面方法也是可以直接使用的 */}

            <button onClick={() => sethook('我改变了react hook 的值' + new Date().getTime())}>改变hook</button>

        </header>

    );

};

 

const Child = (props) => {

    const [ newhook, setnewhook ] = useState(props.hook);

    //这样写可以代替以前的componentDidMount,第二个参数为空数组,表示该useEffect只执行一次

    useEffect(() => {

        console.log('first componentDidMount');

    }, []);

 

    //第二个参数,数组里是hook,当hook变化时,useEffect会触发,当hook变化时,先销毁再执行第一个函数。

    useEffect(

        () => {

            setnewhook(props.hook + '222222222');

            console.log('useEffect');

            return () => {

                console.log('componentWillUnmount ');

            };

        },

        [ props.hook ]

    );

 

    //useLayoutEffect 强制useeffect的执行为同步,并且先执行useLayoutEffect内部的函数

    useLayoutEffect(

        () => {

            console.log('useLayoutEffect');

            return () => {

                console.log('useLayoutEffect componentWillUnmount');

            };

        },

        [ props.hook ]

    );

 

    return (

        <div>

            <p>{props.name}</p>

            {newhook}

        </div>

    );

};

 

export default UseEffect;

useMemo 是做什么的,一言以蔽之,做性能优化用的,如果说类组件的性能优化的方法是 shouldComponentUpdate 和 PureComponent,那么给函数组件做性能优化的就是这个 useMemo。

//parant.jsx
import React, { useState } from 'react';
import Son from '../component/Son'
export default (props)=>{
    const [number,setNumber]=useState(0)
    const [name, setName]=useState('Yui')
    return(
        <div className='flex flex-col'>
        <button className='pb-10' onClick={()=>{setNumber(number+1)}}>{'number is:'+number}</button>
       
        <button onClick={()=>{setName('rena')}}>{'change name'}</button>
        <Son name={name}/>
        </div>
    )
}
//child.jsx
import React, { Component, useMemo } from "react";

export default (props) => {
 const Data= useMemo(() =>{
    console.log('render')
    return props.name+'wowode'
 }, [props.name])
  return (
    <>
      <div>{Data}</div>
    </>
  );
};

useCallback 把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用

import React, {useState, memo, useCallback} from 'react';
function Home(props) {
    console.log('Home被渲染了');
    return (
        <div>
            <p>Home</p>
            <button onClick={()=>{props.handler()}}>增加</button>
        </div>
    )
}
function About(props) {
    console.log('About被渲染了');
    return (
        <div>
            <p>About</p>
            <button onClick={()=>{props.handler()}}>减少</button>
        </div>
    )
}

const MemoHome = memo(Home);
const MemoAbout = memo(About);
function App() {
    console.log('App被渲染了');
    const [numState, setNumState] = useState(0);
    const [countState, setCountState] = useState(0);
    function increment() {
        setNumState(numState + 1);
    }
  
    // 以下代码的作用: 只要countState没有发生变化, 那么useCallback返回的永远都是同一个函数
    const decrement = useCallback(()=>{
        setCountState(countState - 1);
    }, [countState]);
    return (
        <div>
            <p>numState = {numState}</p>
            <p>countState = {countState}</p>
            <MemoHome handler={increment}/>
            <MemoAbout handler={decrement}/>
        </div>
    )
}
export default App;

ohoherror
19 声望1 粉丝