使用 useMemo,useCallback,Reat.memo() 处理不必要的子组件渲染,以及它的实现原理

场景1- 演示一个子组件更新

父组件中一个输入框, 输入值,父组件更新, 同时引入子组件,但子组件也会跟着更新

import React, { useState } from "react";
import ReactDOM from "react-dom";

// 子组件
function Bpp() {
    console.log("%c Bpp render", "color:green");
    return (
        <>
            <div>Bpp组件渲染</div>
        </>
    );
}

// 父组件
function App() {
    const [val, setVal] = useState(100);
    console.log("%c App组件 render", "color:red");
    return (
        <div>
            <span>App组件渲染</span>
            <input value={val} onChange={(e) => setVal(e.target.value)} />
            <hr />
            <Bpp />
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));

此时,子组件并没有任何依赖,但是却产生了不必要的更新, 即还可以再优化下性能
在这里插入图片描述

1.1 解决这种子组件的不必要更新

把子组件 通过 memo()包裹

// 子组件
function Bpp() {
    console.log("%c Bpp render", "color:green");
    return (
        <>
            <div>Bpp组件渲染</div>
        </>
    );
}
// 包裹一下,返回一个组件
Bpp = React.memo(Bpp);

// 父组件
function App() {
    const [val, setVal] = useState(100);
    console.log("%c App组件 render", "color:red");
    return (
        <div>
            <span>App组件渲染</span>
            <input value={val} onChange={(e) => setVal(e.target.value)} />
            <hr />
            <Bpp />
        </div>
    );
}
ReactDOM.render(<App />, document.getElementById("root"));

此时就只渲染父组件了
在这里插入图片描述

场景2- 父组件给子组件传入方法,引起的不必要更新

只要将父组件的方法传给子组件, 不管子组件用不用, 或者父组件的传入的这个方法 是不是又更新操作,都会触发子组件的更新

// 子组件
function Bpp() {
    console.log("%c Bpp render", "color:green");
    return (
        <>
            <div>Bpp组件渲染</div>
        </>
    );
}
// 包裹一下,返回一个组件
Bpp = React.memo(Bpp);

// 父组件
function App() {
    const [name, setName] = useState("hello world");
    console.log("%c App组件 render", "color:red");
    // 父组件的方法,传给子组件
    const handler = () => {
        console.log(10);
    };
    return (
        <div>
            <span>App组件渲染</span>
            <input value={name} onChange={(e) => setName(e.target.value)} />
            <hr />
            {/* 将方法传给子组件 */}
            <Bpp clickHandler={handler} />
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));

此情况下,也会一直触发更新操作
在这里插入图片描述

2.1 使用 useCallback 解决上述的渲染问题

在父组件中使用 useCallback 包裹要触发的函数,同样的第二个参数就是依赖项, 依赖项变化,也是会触发更新

function App() {
    const [name, setName] = useState("hello");

    console.log("%c App组件 render", "color:red");

    // useCallback(_, []), 第二个参数还是 依赖项
    const handler = useCallback(() => {
        console.log(10);
    }, []);

    return (
        <div>
            <span>App组件渲染</span>
            <input value={name} onChange={(e) => setName(e.target.value)} />
            <hr />
            {/* 将方法传给子组件 */}
            <Bpp clickHandler={handler} />
        </div>
    );
}

在这里插入图片描述

场景3-, 父组件的某个值和方法都传给子组件

描述场景: 对单一基本数据类型再进行一次包装, 将它作为某个新对象的某个属性的值

// 子组件
function Bpp(props) {
    console.log("%c Bpp render", "color:green");
    return (
        <>
            <button onClick={props.click}>Bpp组件渲染</button>
        </>
    );
}
// 包裹一下,返回一个组件
Bpp = React.memo(Bpp);

// 父组件
function App() {
    const [num, setNum] = useState(1);
    const [name, setName] = useState("jklov");

    console.log("%c App组件 render", "color:red");

    // 父组件的方法
    const clickHandler = useCallback(() => {
        setNum(num + 1);
    }, []);

    // 对 num 包一层
    let data = { num };
    // let data = useMemo(() => ({ num }), []);
    return (
        <div>
            <span>App组件渲染</span>
            <input value={name} onChange={(e) => setName(e.target.value)} />
            <hr />
            {/* 将方法传给子组件 */}
            <Bpp data={data} click={clickHandler} />
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));

依旧触发子组件的更新
在这里插入图片描述
使用 useMomo 包裹一下

//... 略
let data = useMemo(() => ({ num }), []);
// ...略

在这里插入图片描述
实现原理。。。后续补。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值