通过案例讲解react函数式组件优化函数memo!

react现在函数式组件大行其道,但少有人将优化函数式组件的memo讲得简单明了。下文将通过案例来讲解memo。

案例

先看代码:

import React, { memo } from "react";

const Demo = () => {
  let [food1, setFood1] = React.useState(20);
  let [food2, setFood2] = React.useState(20);
  const reduce1 = () => {
    setFood1(food1 > 0 ? food1 - 1 : 0);
  };
  const reduce2 = () => {
    setFood2(food2 > 0 ? food2 - 1 : 0);
  };
  console.log("父组件被渲染了");
  return (
    <>
      <h3>肉包还有{food1}</h3>,<button onClick={reduce1}>肉包卖了一个</button>
      <br />
      <h3>菜包还有{food2}</h3>,<button onClick={reduce2}>菜包卖了一个</button>
      <br />
      <br />
      <Food1 count={food1} />
      <Food2 count={food2} />
    </>
  );
};
export default Demo;
const Food1 = memo(
  (props) => {
    console.log("子组件food1被渲染了");
    return <h4>肉包只有{props.count}个了!</h4>;
  },
  (preProps, nextProps) => preProps.count === nextProps.count
);

const Food2 = (props) => {
  console.log("子组件food2被渲染了");
  return <h4>菜包只有{props.count}个了!</h4>;
};

讲解

上面的代码创建了1个父组件和2个子组件,其中子组件Food1使用了memo函数,子组件Food2未使用memo函数。
接下来通过sudo yarn start来启动项目,打开控制台,认真观察日志。

日志详解

首次打开页面

首次打开页面时日志显示如下内容,说明所有组件首次挂载到页面全部会渲染。

父组件被渲染了
子组件food1被渲染了
子组件food2被渲染了

点击按钮一

点击“肉包卖了一个”按钮后,可以看到父组件和2个子组件都渲染了。按理来说父组件和子组件food1的数据有变动,这2个组件渲染是合理的,但子组件food2也被渲染,这是不合理的,可以进行优化,避免无谓的页面渲染。

父组件被渲染了
子组件food1被渲染了
子组件food2被渲染了

点击按钮二

请注意看认真,点击“菜包卖了一个”按钮按钮后,可以看到父组件和food2子组件被渲染了,子组件food1未被渲染!!!

父组件被渲染了
子组件food2被渲染了

对比代码

请认真对比food1和food2子组件的代码差异:

food1的代码

const Food1 = memo(
  (props) => {
    console.log("子组件food1被渲染了");
    return <h4>肉包只有{props.count}个了!</h4>;
  },
  (preProps, nextProps) => preProps.count === nextProps.count
);

food2的代码

const Food2 = (props) => {
  console.log("子组件food2被渲染了");
  return <h4>菜包只有{props.count}个了!</h4>;
};

讲解

Food1子组件可以做到props不变时页面不重复渲染的秘诀在于该子组件被高阶函数memo包裹。
memo是一个高阶函数,它有两个参数。

  • 参数一是必须是函数组件;
  • 参数二是可选参数:
    • 不传参时,memo会对函数组件中的state、props做浅比较,有变化才调用函数组件(参数一)进行渲染,没变化则不调用函数组件(参数一)进行渲染。
    • 若传参时,该参数必须是返回true或false的函数。当返回值为true时,memo则不会调用参数一,即组件不会重新渲染;当返回值为false时,memo会调用参数一,即组件会重新渲染。

结果

希望各位读者参照组件Food1对组件Food2进行优化,最终达到点击按钮“肉包卖了一个”时组件Food2不渲染、点击按钮“菜包卖了一个”时组件Food1不渲染。希望要理解memo的读者一定要亲手尝试敲代码!!!敲过了才能真正理解!!

Food子组件优化版

const Food2 = memo(
    (props) => {
  		console.log("子组件food2被渲染了");
		return <h4>菜包只有{props.count}个了!</h4>;
	},  // 参数二缺省,按默认情况做浅比较
);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值