自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

React性能優(yōu)化之useMemo、useCallback

開發(fā) 前端
記憶化用于提高React應(yīng)用程序的性能,記憶化用于跳過組件的不必要重新渲染。useMemo和useCallback?鉤子分別用于記憶化返回值和函數(shù)聲明。雖然useMemo和useCallback?的行為類似,但兩者之間存在關(guān)鍵差異。useMemo?返回調(diào)用函數(shù)的結(jié)果;useCallback返回函數(shù)本身。

前言

在React應(yīng)用程序中進(jìn)行性能優(yōu)化至關(guān)重要,因為它直接影響用戶體驗,隨后影響轉(zhuǎn)化率和用戶留存率。一個經(jīng)過優(yōu)化的React應(yīng)用加載更快,響應(yīng)迅速,消耗更少的資源,從而為用戶提供更順暢的互動體驗。優(yōu)化React應(yīng)用程序的性能對于保留和吸引用戶、降低跳出率以及最終實現(xiàn)所期望的業(yè)務(wù)結(jié)果至關(guān)重要。

記憶化(Memoization)是改善React應(yīng)用程序性能的一種方式。記憶化涉及緩存值和函數(shù)以實現(xiàn)更快的渲染。

在本文中,我們將了解什么是記憶化以及如何使用useMemo和useCallback鉤子來實現(xiàn)記憶化。

理解React中的記憶化

記憶化是存儲計算結(jié)果的過程,以便在不重新計算的情況下檢索它。記憶化用于跳過組件的不必要重新渲染。

在React中,可以通過使用useMemo和useCallback鉤子來實現(xiàn)記憶化。這些鉤子允許你通過緩存函數(shù)調(diào)用和函數(shù)本身來跳過重新渲染。

使用useMemo入門

useMemo鉤子用于緩存函數(shù)調(diào)用。useMemo鉤子接受兩個參數(shù):

  • 函數(shù)
  • 依賴項數(shù)組
const doubledNumber = useMemo(() => {
  return someExpensiveCalculation(number);
}, [number]);

useMemo鉤子在第一次渲染時返回調(diào)用函數(shù)的結(jié)果。在后續(xù)重新渲染中,useMemo鉤子將提供你的函數(shù)調(diào)用的緩存值,除非至少一個依賴項發(fā)生更改。

在JavaScript中,函數(shù)在代碼再次運行時會被重新創(chuàng)建。這意味著盡管函數(shù)的代碼相同,但每次應(yīng)用程序重新渲染時,你的函數(shù)并不相同。這是因為JavaScript對象和函數(shù)是引用對象。

useMemo鉤子旨在通過緩存調(diào)用函數(shù)的結(jié)果來消除函數(shù)的重新創(chuàng)建。在后續(xù)重新渲染中,useMemo鉤子會返回緩存的值,跳過函數(shù)的重新創(chuàng)建。

讓我們通過一個實際示例來了解如何在React中使用useMemo。

在這個示例中,我們正在對幾千篇博客文章進(jìn)行排序,并將每篇博客文章顯示在屏幕上。在每次重新渲染時對博客文章進(jìn)行排序可能會減慢我們的應(yīng)用程序。

使用useMemo鉤子來跳過博客文章的排序,如果文章列表沒有更改。

function PostList({ posts }) {
  const sortedPosts = useMemo(() => {
    return [...posts].sort((a, b) => a.date - b.date);
  }, [posts]);

  return (
    <div>
      <h2>已排序的文章</h2>
      <ul>
        {sortedPosts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

useMemo鉤子用于緩存sortedPosts。只有在posts的值更改時,sortedPosts才會重新計算。

通過這種方式,排序操作僅在文章數(shù)組更改時發(fā)生,從而跳過重新渲染并提高性能。

充分利用useCallback的能力

useCallback用于緩存函數(shù)聲明。它同樣接受兩個參數(shù):

  • 函數(shù)
  • 依賴項數(shù)組

與useMemo不同,useCallback不會調(diào)用你的函數(shù)。useCallback只是將函數(shù)返回給你。你可以自行決定何時以及是否調(diào)用函數(shù)。

useCallback鉤子的工作方式與useMemo鉤子類似。useCallback通過返回函數(shù)的緩存版本來消除函數(shù)的重新創(chuàng)建。只有在依賴項中的至少一個值發(fā)生更改時,才會重新創(chuàng)建你的函數(shù)。

讓我們看一個使用useCallback來優(yōu)化React應(yīng)用程序的示例。

在React組件中,當(dāng)單擊按鈕時,你有一個對產(chǎn)品數(shù)組進(jìn)行排序的函數(shù)。在每次重新渲染時,這個排序函數(shù)都會被重新創(chuàng)建。

使用useCallback鉤子來緩存sortPosts函數(shù)聲明,以及posts狀態(tài)作為一個依賴項。

import React, { useState, useCallback } from 'react';

function PostList() {
  const [posts, setPosts] = useState([
    { id: 1, title: '文章1', date: new Date('2023-10-15T00:00:00.000Z') },
    { id: 2, title

: '文章2', date: new Date('2023-10-10T00:00:00.000Z') },
    { id: 3, title: '文章3', date: new Date('2023-10-20T00:00:00.000Z') },
  ]);

  const sortPosts = useCallback(() => {
    const sortedPosts = [...posts].sort((a, b) => a.date - b.date);
    setPosts(sortedPosts);
  }, [posts]);

  return (
    <div>
      <button onClick={sortPosts}>排序文章</button>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        )}
      </ul>
    </div>
  );
}

export default PostList;

現(xiàn)在,只有當(dāng)posts狀態(tài)更改時,sortPosts函數(shù)才會被重新創(chuàng)建,從而提高我們的React應(yīng)用程序性能。

通過結(jié)合使用useCallback和useMemo來優(yōu)化性能

useCallback和useMemo鉤子可以一起使用,以獲得顯著的性能提升。

React組件重新渲染依賴以下兩個條件:

  • 狀態(tài)發(fā)生變化
  • 屬性發(fā)生變化

通過useCallback鉤子,你可以緩存屬性(如果是一個函數(shù)),然后將其傳遞給包裝在useMemo中的子組件。

接下來看一個將useCallback與useMemo結(jié)合使用的示例。

假設(shè)你正在為網(wǎng)站開發(fā)產(chǎn)品列表頁面。用戶可以根據(jù)價格、品牌和類別等各種標(biāo)準(zhǔn)對產(chǎn)品進(jìn)行篩選和排序。

如果不使用useCallback和useMemo鉤子,你的ProductList組件將如下所示:

javascriptCopy code
import React, { useState } from 'react';

function ProductList({ products }) {
  const [filter, setFilter] = useState('');
  const [sortBy, setSortBy] = useState('price');

  // 根據(jù)用戶輸入篩選產(chǎn)品
  const filteredProducts = products.filter(product =>
    product.title.toLowerCase().includes(filter.toLowerCase())
  );

  // 對篩選后的產(chǎn)品進(jìn)行排序
  const sortedProducts = [...filteredProducts].sort((a, b) => {
    if (sortBy === 'price') {
      return a.price - b.price;
    } else if sortBy === 'rating') {
      return b.rating - a.rating;
    }
    // 在這里處理其他排序條件
  });

  // 處理篩選更改
  const handleFilterChange = (event) => {
    setFilter(event.target.value);
  };

  // 處理排序更改
  const handleSortChange = (event) => {
    setSortBy(event.target.value);
  };

  return (
    <div>
      <input
        type="text"
        placeholder="篩選產(chǎn)品"
        value={filter}
        onChange={handleFilterChange}
      />
      <select value={sortBy} onChange={handleSortChange}>
        <option value="price">價格</option>
        <option value="rating">評分</option>
        {/* 根據(jù)需要添加更多排序選項 */}
      </select>
      <ul>
        {sortedProducts.map(product => (
          <li key={product.id}>{product.title}</li>
        )}
      </ul>
    </div>
  );
}

export default ProductList;

雖然ProductList組件沒有問題,但它可能導(dǎo)致不必要的重新渲染和性能瓶頸。

如果ProductList處理大量產(chǎn)品,不必要的重新渲染會減慢你的電子商務(wù)站點。

使用useMemo和useCallback鉤子來減輕不必要的重新渲染并加速你的網(wǎng)站。

javascriptCopy code
import React, { useState, useMemo, useCallback } from 'react';

function ProductList({ products }) {
  const [filter, setFilter] = useState('');
  const [sortBy, setSortBy] = useState('price');

  // 根據(jù)用戶輸入篩選產(chǎn)品
  const filteredProducts = useMemo(() => {
    return products.filter(product => product.title.toLowerCase().includes(filter.toLowerCase()));
  }, [products, filter]);

  // 對篩選后的產(chǎn)品進(jìn)行排序
  const sortedProducts = useMemo(() => {
    return [...filteredProducts].sort((a, b) => {
      if (sortBy === 'price') {
        return a.price - b.price;
      } else if sortBy === 'rating') {
        return b.rating - a.rating;
      }
      // 在這里處理其他排序條件
    });
  }, [filteredProducts, sortBy]);

  // 記憶化回調(diào)來處理篩選更改
  const handleFilterChange = useCallback((event) => {
    setFilter(event.target.value);
  }, []);

  // 記憶化回調(diào)來處理排序更改
  const handleSortChange = useCallback((event) => {
    setSortBy(event.target.value);
  }, []);

  return (
    <div>
      <input
        type="text"
        placeholder="篩選產(chǎn)品"
        value={filter}
        onChange={handleFilterChange}
      />
      <select value={sortBy} onChange={handleSortChange}>
        <option value="price">價格</option>
        <option value="rating">評分</option>
        {/* 根據(jù)需要添加更多排序選項 */}
      </select>
      <ul>
        {sortedProducts.map(product => (
          <li key={product.id}>{product.title}</li>
        )}
      </ul>
    </div>
  );
}

export default ProductList;

在這個經(jīng)過優(yōu)化的ProductList組件版本中,useMemo用于優(yōu)化篩選和排序操作,而useCallback用于記憶化篩選和排序更改的事件處理程序函數(shù)。ProductList組件僅在products的值發(fā)生變化時重新渲染。

注意事項

盡管useMemo和useCallback是性能優(yōu)化鉤子,但開發(fā)人員往往會過度使用這些鉤子。有些情況下,使用useMemo和useCallback并不對你的應(yīng)用程序產(chǎn)生大的收益。由于現(xiàn)代計算機(jī)的快速性質(zhì),大多數(shù)操作都是廉價的。在操作廉價的情況下,你不需要useMemo和useCallback鉤子。例如,你有一個要排序的包含100個帖子的數(shù)組。使用useMemo或useCallback鉤子不會帶來任何性能提升,因為排序操作只需要幾毫秒。

總結(jié)

記憶化用于提高React應(yīng)用程序的性能,記憶化用于跳過組件的不必要重新渲染。useMemo和useCallback鉤子分別用于記憶化返回值和函數(shù)聲明。雖然useMemo和useCallback的行為類似,但兩者之間存在關(guān)鍵差異。useMemo返回調(diào)用函數(shù)的結(jié)果;useCallback返回函數(shù)本身。

useMemo和useCallback鉤子有助于優(yōu)化性能,但使用它們也可能帶來一些潛在問題,如過度優(yōu)化和增加代碼復(fù)雜性。

責(zé)任編輯:武曉燕 來源: 前端大濕兄
相關(guān)推薦

2025-04-03 07:37:55

2021-08-27 14:26:06

開發(fā)技能React

2019-02-25 07:07:38

技巧React 優(yōu)化

2023-12-20 14:48:26

2022-08-03 09:11:31

React性能優(yōu)化

2016-12-19 10:00:00

React性能優(yōu)化

2023-11-29 09:00:55

ReactuseMemo

2023-02-14 06:40:33

React HookReact

2021-07-29 14:20:34

網(wǎng)絡(luò)優(yōu)化移動互聯(lián)網(wǎng)數(shù)據(jù)存儲

2020-06-22 07:30:00

React開發(fā)工具

2022-02-16 14:10:51

服務(wù)器性能優(yōu)化Linux

2021-11-29 11:13:45

服務(wù)器網(wǎng)絡(luò)性能

2019-03-14 15:38:19

ReactJavascript前端

2018-01-09 16:56:32

數(shù)據(jù)庫OracleSQL優(yōu)化

2019-12-13 10:25:08

Android性能優(yōu)化啟動優(yōu)化

2009-06-30 11:23:02

性能優(yōu)化

2025-01-20 09:09:59

2023-07-19 12:24:48

C++constexpr?語句

2011-07-11 15:26:49

性能優(yōu)化算法

2013-02-20 14:32:37

Android開發(fā)性能
點贊
收藏

51CTO技術(shù)棧公眾號