关于低端机React性能优化的两条建议

300 阅读3分钟

虽然说React性能目前来说比不上vue,但是我们可以通过一些优化手段来优化代码,优化在低端机上的响应速度。我们可以根据INP这项指标来衡量我们的性能,也就是说,对于用户操作的响应速度越快,性能越好。

用到的工具

chrome.google.com/webstore/de…

image.png

如何模拟低端机

性能面板选择cpu的降速,推荐20倍,优化效果更明显。 image.png

提升性能优化

减少不必要的组件删除和重建

尽量不要使用条件渲染销毁重建十分巨大的组件,但是如果必须这么做,那我们可以合理运用startTransitionuseDefferened,首先我们来看一个例子:

import React from 'react';
import './App.scss';
import 'swiper/css';
import { Swiper, SwiperSlide } from 'swiper/react';

type ReviewImageProps = {
  images: string[];
  visible: boolean;
  activeIndex: number;

  onMaskClick: () => void;
};
const ReviewImage: React.FC<ReviewImageProps> = (props) => {
  const { images, activeIndex, onMaskClick } = props;

  const swiperSlideElementArray = images.map((img, index) => {
    return (
      <SwiperSlide key={index}>
        <img
          onClick={(event) => {
            event.stopPropagation();
          }}
          key={index}
          src={img}
          className="lookImg"
        />
      </SwiperSlide>
    );
  });

  return (
    <div
      className="mask"
      onClick={() => {
        onMaskClick();
      }}
    >
      {(
        <Swiper initialSlide={activeIndex} slidesPerView={1}>
          {swiperSlideElementArray}
        </Swiper>
      )}
    </div>
  );
};

function App() {
  const [visible, setVisible] = React.useState(false);
  const [activeIndex, setActiveIndex] = React.useState(0);
  const imgs = [
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
  ];

  const imageElementArray = imgs.map((img, index) => (
    <img
      src={img}
      key={index}
      onClick={() => {
        setActiveIndex(index);
        setVisible(true);
      }}
    />
  ));

  const handleOnMaskClick = () => {
    setVisible(false);
  };

  return (
    <div>
      {visible && (
        <ReviewImage
          visible={visible}
          onMaskClick={handleOnMaskClick}
          activeIndex={activeIndex}
          images={imgs}
        />
      )}
      <div className="previewImage">{imageElementArray}</div>
    </div>
  );
}

export default App;

image.png

这是一个简单的图片预览预览图使用swiper,但是我们可以发现此时在20倍降速INP非常差,此时我们用useDefferened来让遮罩层渲染:

const ReviewImage: React.FC<ReviewImageProps> = (props) => {
  const { images, activeIndex, onMaskClick } = props;
  const [visible, setVisible] = React.useState(false);
  const defferValue = React.useDeferredValue(visible); // 让遮罩层先渲染,再渲染Swiper

  const swiperSlideElementArray = images.map((img, index) => {
    return (
      <SwiperSlide key={index}>
        <img
          onClick={(event) => {
            event.stopPropagation();
          }}
          key={index}
          src={img}
          className="lookImg"
        />
      </SwiperSlide>
    );
  });

  React.useEffect(() => {
    setVisible(true);
  }, []);

  return (
    <div
      className="mask"
      onClick={() => {
        onMaskClick();
      }}
    >
      {defferValue && (
        <Swiper initialSlide={activeIndex} slidesPerView={1}>
          {swiperSlideElementArray}
        </Swiper>
      )}
    </div>
  );
};

image.png

可以发现INP优化了不少。当然这是种特殊情况,我们不得以需要删除重建组件,一般情况我们可以使用display显示隐藏预览组件来减少组件卸载重建,减少INP

import React from 'react';
import './App.scss';
import 'swiper/css';
import { Swiper, SwiperSlide } from 'swiper/react';

type ReviewImageProps = {
  images: string[];
  visible: boolean;
  activeIndex: number;

  onMaskClick: () => void;
};
const ReviewImage: React.FC<ReviewImageProps> = (props) => {
  const { images, activeIndex, visible, onMaskClick } = props;

  const swiperSlideElementArray = images.map((img, index) => {
    return (
      <SwiperSlide key={index}>
        <img
          onClick={(event) => {
            event.stopPropagation();
          }}
          key={index}
          src={img}
          className="lookImg"
        />
      </SwiperSlide>
    );
  });

  // 使用display来优化INP
  return (
    <div
      className="mask"
      style={{ display: visible ? 'block' : 'none' }} 
      onClick={() => {
        onMaskClick();
      }}
    >
      {
        <Swiper initialSlide={activeIndex} slidesPerView={1}>
          {swiperSlideElementArray}
        </Swiper>
      }
    </div>
  );
};

function App() {
  const [visible, setVisible] = React.useState(false);
  const [activeIndex, setActiveIndex] = React.useState(0);
  const imgs = [
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
  ];

  const imageElementArray = imgs.map((img, index) => (
    <img
      src={img}
      key={index}
      onClick={() => {
        setActiveIndex(index);
        setVisible(true);
      }}
    />
  ));

  const handleOnMaskClick = () => {
    setVisible(false);
  };

  return (
    <div>
      <ReviewImage
        visible={visible}
        onMaskClick={handleOnMaskClick}
        activeIndex={activeIndex}
        images={imgs}
      />
      <div className="previewImage">{imageElementArray}</div>
    </div>
  );
}

export default App;

image.png

可以发现效果也很好

合理运用useMemo

或许你听说,一般情况下useMemo,useCallback,memo这三个函数一般不需要使用,但是在js中迭代是非常耗时的,所以合理运用useMemo,可以提升我们的性能。我们先看不包裹useMemo的情况下迭代用了多长时间:

image.png 可以发现平均达到了4ms,但是如果我们用useMemo包裹之后就可以发现提升了不少:

image.png 可以发现此时减少了4ms

我们可以发现之前使用display的例子并没有使用useDefferened的效果来的那么好,我们可以尝试使用useMemo来包裹迭代:

import React from 'react';
import './App.scss';
import 'swiper/css';
import { Swiper, SwiperSlide } from 'swiper/react';

type ReviewImageProps = {
  images: string[];
  visible: boolean;
  activeIndex: number;

  onMaskClick: () => void;
};
const ReviewImage: React.FC<ReviewImageProps> = (props) => {
  const { images, activeIndex, visible, onMaskClick } = props;

  // 使用useMemo
  const swiperSlideElementArray = React.useMemo(
    () =>
      images.map((img, index) => {
        return (
          <SwiperSlide key={index}>
            <img
              onClick={(event) => {
                event.stopPropagation();
              }}
              key={index}
              src={img}
              className="lookImg"
            />
          </SwiperSlide>
        );
      }),
    []
  );

  return (
    <div
      className="mask"
      style={{ display: visible ? 'block' : 'none' }}
      onClick={() => {
        onMaskClick();
      }}
    >
      {
        <Swiper initialSlide={activeIndex} slidesPerView={1}>
          {swiperSlideElementArray}
        </Swiper>
      }
    </div>
  );
};

function App() {
  const [visible, setVisible] = React.useState(false);
  const [activeIndex, setActiveIndex] = React.useState(0);
  const imgs = [
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/07/11/07/01/horse-4330166_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
    'https://cdn.pixabay.com/photo/2023/11/26/23/43/horse-8414411_960_720.jpg',
    'https://cdn.pixabay.com/photo/2017/06/30/00/04/pony-2456757_640.jpg',
    'https://cdn.pixabay.com/photo/2020/06/19/08/31/haflinger-5316218_1280.jpg',
  ];

  // 使用useMemo
  const imageElementArray = React.useMemo(
    () =>
      imgs.map((img, index) => (
        <img
          src={img}
          key={index}
          onClick={() => {
            setActiveIndex(index);
            setVisible(true);
          }}
        />
      )),
    []
  );

  const handleOnMaskClick = () => {
    setVisible(false);
  };

  return (
    <div>
      <ReviewImage
        visible={visible}
        onMaskClick={handleOnMaskClick}
        activeIndex={activeIndex}
        images={imgs}
      />
      <div className="previewImage">{imageElementArray}</div>
    </div>
  );
}

export default App;

image.png

可以发现INP更加短了,减少了一些不必要的迭代时间

相关示例的代码: github.com/RadiumAg/ja…