美文网首页大前端
useMemo, useCallback, useEffect

useMemo, useCallback, useEffect

作者: jack钱 | 来源:发表于2023-03-21 16:53 被阅读0次

    useEffect

    • useEffect是在DOM改变之后触发
    • useEffect可以帮助我们在DOM更新完成后执行某些副作用操作
    • 诸如副作用这类的操作属于 useEffect 的适用范畴

    useMemo

    • 父组件将一个 加工后的【值】绑定到页面,若父组件的其他值发生变化时,加工的函数也会跟着渲染多次,会造成性能浪费; useMemo是将函数的值缓存起来,只有当 useMemo中的第二个参数状态变化时,函数才重新加载
    • useMemo便是用于缓存该函数的执行结果,仅当依赖项改变后才会重新计算
    修改后如下,注意useMemo缓存的是函数执行的结果, 只有当[count, price]改变时才会重走一遍
    
    const Parent = () => {
        const [count, setCount] = useState(0);
        const [color,setColor] = useState("");
        const [price,setPrice] = useState(10);
        const handleClick = () => {
            setCount(count + 1);
        }
        const getTotal = useMemo(()=>{
            console.log("getTotal exec ...") 
            return count * price
        },[count, price])
        
        return (<div>
            <div> <input onChange={(e) => setColor(e.target.value)}/></div>
            <div> <input value={price}  onChange={(e) => setPrice(Number(e.target.value))}/></div>
            <div> {count} <button onClick={handleClick}>+1</button></div>
            <div> {getTotal}</div>
        </div>)
    }
    

    memo

    • 父组件 text 或 任何 属性变化都会导致 Child 函数重新执行,所以即使传入子组件props没有任何变化,甚至子组件没有依赖于任何props属性,都会导致子组件重新渲染
    • 使用memo包裹子组件时,只有props发生改变子组件才会重新渲染,以提升一定的性能
    const Child = memo((props: any) => {
        console.log("子组件更新..."); // 只有当props属性改变,name属性改变时,子组件才会重新渲染
        return (
            <div>
                <h3>子组件</h3>
                <div>text:{props.name}</div>
                <div>{new Date().getTime()}</div>
            </div>
        )
    })
    
    
    const Parent = () => {
        const [text, setText] = useState("")
        …… ……
        <Child name ={text}/>
    }
    

    useCallback

    • 父组件将一个【方法】传递给子组件,若父组件的其他状态发生变化(数据改变)时,作为props的函数也会产生新的实例,导致函数重新执行,子组件也会跟着渲染多次,会造成性能浪费; usecallback是将父组件传给子组件的方法给缓存下来,只有当 usecallback中的第二个参数状态变化时,子组件才重新渲染
    • useCallback 应该搭配 memo 用作优化子组件,防止子组件重复渲染
    const Child = memo((props: any) => {
        console.log("子组件更新..."); // 父级Parent函数有东西变化,Child重新执行,handleInputChange已经指向新的函数实例,所以子组件依然会刷新
        return (
            <div>
                <div>text:{props.name}</div>
                <div> <input onChange={props.handleInputChange} /></div>
            </div>
        )
    })
    const Parent = () => {
        const [text, setText] = useState("")
        const [count, setCount] = useState(0)
        const handleInputChange =useCallback((e) => {
             setText(e.target.value )
        },[]) 
        return (<div>
                …… ……
            <Child name={text} handleInputChange={handleInputChange}/>
        </div>)
    }
    
    • useCallback返回一个函数,当把它返回的这个函数作为子组件使用时,可以避免每次父组件更新时都重新渲染这个子组件
    const renderButton = useCallback(
         () => (
             <Button type="link">
                {buttonText}
             </Button>
         ),
         [buttonText]    // 当buttonText改变时才重新渲染renderButton
    );
    

    引用:useMemo, useCallback, useEffect 三者区别 - 掘金 (juejin.cn)

    相关文章

      网友评论

        本文标题:useMemo, useCallback, useEffect

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