使用 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 }), []);
// ...略

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`React.memo` 是 React 中的一个高阶组件,用于优化组件的性能。它与 `React.PureComponent` 类似,但适用于函数组件而不是类组件使用 `React.memo` 可以避免在某些情况下不必要的重渲染。当组件的 props 发生变化时,React 会重新渲染组件。但如果 props 没有发生变化,就没有必要重新渲染组件。这时,`React.memo` 就可以发挥作用。 `React.memo` 的基本用法如下: ```jsx import React from 'react'; function MyComponent(props) { // 组件渲染逻辑 } export default React.memo(MyComponent); ``` 在这个例中,我们将 `MyComponent` 组件使用 `React.memo` 包裹起来,这样就可以实现组件的记忆功能。当 `MyComponent` 组件的 props 发生变化时,`React.memo` 会比较前后两个 props 是否相等,如果相等就不会重新渲染组件,否则就会重新渲染组件。 需要注意的是,`React.memo` 只会对 props 进行浅比较,因此如果 props 是一个对象或数组,而且它们的值发生了变化,但引用没有变化,`React.memo` 仍然会认为它们相等。在这种情况下,你需要手动处理 props 的深层次变化,或者使用其他的优化工具,例如 `useMemo`、`useCallback` 等等。 另外,需要注意的是,虽然 `React.memo` 可以帮助我们优化组件的性能,但也不应该滥用。在大多数情况下,React 自身已经能够很好地处理组件渲染,并且重渲染通常也不会带来太大的性能问题。只有在某些情况下,例如组件渲染比较频繁,或者组件渲染成本比较高时,才需要考虑使用 `React.memo` 进行优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值