如何在React中优化缓存的方法?详细指南

2021年11月30日02:49:18 发表评论 1,630 次浏览
如何在React中优化缓存的方法?详细指南
React优化缓存实例教程

作为用于创建高性能 Web 应用程序的最受欢迎的前端库之一,React 遵循基于组件的方法,其中每个组件都有自己的状态和逻辑。

如何在React中优化缓存?React 面临的最大挑战是避免不必要的渲染,这会导致严重的性能问题,尤其是在大型应用程序中。在本文中,我们将介绍几种不同的方法,通过不同的缓存方法来优化 React 应用程序的性能。

React优化缓存的方法:用于记忆的 React Hooks

记忆(Memoization)是 React 本身提供的一个特性。正如我们所知,React 每次重新渲染时都会创建新的引用。如果你的组件有大量计算,即使输出没有改变,也会在每次重新渲染时进行计算。

为了通过避免不必要的负载来使 CPU 负载最小化,React 提供了两个有助于记忆的 Hook。Hooks 遵循一个过程,其中结果被缓存在内存中,当我们得到相同的输入时,无需重新计算就返回。在不同输入的情况下,缓存失效。

useMemo()

React优化缓存实例教程:useMemo()是 React 提供的用于记忆的 Hook,有助于保持缓存值与提供给它的值相同。它跟踪输入并返回先前执行的结果。

让我们看一个例子。假设我们必须在具有以下功能的组件中添加两个巨大的数字:

const addTwoHugeNumbers=(a,b)=>{
return a+b
}

上面写的函数对 CPU 来说很重,因此应该只在a和的值b改变时计算。但是,默认情况下,它将在每次重新渲染时运行。

使用useMemo(),我们可以存储特定值的结果,这意味着函数不会计算,我们将直接获得先前计算的结果:

const memoizedValue = useMemo(() => addTwoHugeNumbers(a, b), [a, b])

该值存储在memoizedValue. 我们已经将依赖数组传递给useMemo,它告诉它什么时候再次运行。在我们的例子中,它会在任何一个值改变时运行。

UseCallback()

使用useCallback(),我们也获得了记忆的能力,但它以不同的方式工作。useCallback()不记忆值,而是记忆提供给它的回调函数。让我们看一个小例子:

const increment = (() => {
  setCount(count + 1);
});

使用useCallback(),上面的函数类似于下面的代码:

const increment = useCallback(() => {
  setCount(count + 1);
}, [count]);

useCallback()将记住增量函数,仅在给定的依赖项发生变化时运行。它不跟踪输入或函数返回的值。

延迟加载 React 组件

如何在React中优化缓存?React 中的延迟加载会预先呈现必要的组件,并将加载不重要的组件延迟到之后。

特别是在较大的应用程序中,强烈建议使用这种方法来提高性能。在 React 中,我们有内置选项来延迟加载组件。

我们已经创建了一个名为的组件</Artists>,我们希望它延迟加载,我们可以这样做:

import { lazy } from 'react';

首先,我们从 react 中导入 lazy 并使用它,如下所示:

const Artists = React.lazy(() => import('./Artists'));

function App() {
  return (
    <div>
      <Artists />
    </div>
  );
}

useRef()

React优化缓存的方法:我们知道,无论何时在组件中使用useState(),当状态改变时,它都会在组件中重新呈现。为了跟踪状态而不引起重新呈现,React引入了useRef()钩子。

在某些情况下,useState()可能不是您的应用程序的正确解决方案。useRef()非常适合于这样的情况:我们需要的状态不会导致重新呈现,并且对组件呈现的可见信息没有贡献。例如,你可以用它来计数渲染:

function App() {
    const [foo, setFoo] = React.useState(false)
    const counter = React.useRef(0)
    console.log(counter.current++)
    return (
      <button onClick={() => setFoo(f => !f)} > Click </button>
     )
}

ReactDOM.render(<React.StrictMode><App /></React.StrictMode>, document.getElementById('mydiv'))

在上面的代码中,我们有一个简单的切换器,用于重新呈现组件。Counter是一个持久化其值的可变ref。我们可以对useState()做同样的事情,但它会为每个切换导致两次呈现。

React优化缓存实例教程:Redux 缓存选择器

选择器只是用于从更大的数据池中选择数据的函数。在 React 中,选择器被广泛用于从 Redux 存储中获取值。选择器非常有用和强大,但它们也有自己的缺点。

在React Redux中,我们有useSelector()钩子,用于从商店获取状态。useSelector()的问题在于它在组件每次呈现时都会运行。useSelector()在某些情况下可能是理想的,但大多数情况下,选择器返回的数据不会改变,这使得不必要的计算。

让我们看一个例子:

import React, {useEffect,useState} from 'react'
import {useSelector, useDispatch} from 'react-redux'
import {getPosts} from './postActions'

export const List=()=>{
  Const [toggle, setToggle]=useState(false)
  const myPosts=useSelector(state=>state.posts)
  const dispatch=useDispatch()


  return(
    <div>
    {myPosts.map(post=><p>{posts}<p/>)}
    <button type="button" onClick={()=>{setToggle(!toggle)}} >Click Me!</button>
    <div/>
  )
}

在上面的代码中,我们正在更改切换状态,并且每次我们执行此操作时组件都会呈现。该挂钩也将运行,即使职位不符合我们的终极版店内改变。useSelector()

为了解决这个问题,我们将缓存一个选择器函数的结果。尽管没有内置的 React 解决方案,但我们有许多第三方库允许我们创建缓存选择器。让我们使用 Reselect,这是缓存选择器的著名解决方案。

Reselect

React优化缓存的方法:Reselect 是一个流行的库,用于创建记忆化选择器。你可以使用以下命令将其安装到你的项目中:

yarn add reselect

我们可以使用 Reselect 如下:

import { createSelector } from 'reselect' 
import React, {useEffect,useState} from 'react'
import {useSelector, useDispatch} from 'react-redux'
import {getPosts} from './postActions'

export const List=()=>{
  Const [toggle, setToggle]=useState(false)
  const myPosts = createSelector(state=>state.posts)
  const dispatch=useDispatch()


  return(
  <div>
  {myPosts.map(post=><p>{posts}<p/>)}
  <button type="button" onClick={()=>{setToggle(!toggle)}} >Click Me!</button>
  <div/>
  )
}

在上面的代码中,我们createSelector从 Reselect导入,它接受一个选择器并返回它的记忆版本。使用记忆化版本,即使经过数千次重新渲染,组件也不会计算选择器的值,除非值发生postReducer变化。createSelector事实证明,Reselect 是解决大型应用程序性能问题的绝佳解决方案。

使用 React Query 优化 API 调用

如何在React中优化缓存?React 以自己的方式处理异步操作,这有时是开发人员的一个问题。异步操作的常用模式是在useEffectHook 中获取服务器数据,它在每次渲染时运行并每次获取新数据,即使服务器上没有新数据。

另一方面,React Query 缓存数据并在调用之前先返回它,但是如果服务器返回的新数据与之前的数据相同,React Query 将不会重新渲染组件。我们可以使用 React Query 如下:

import React from 'react'
import {useQuery} from 'react-query'
import axios from 'axios'

async function fetchPosts(){
    const {data} = await axios.get('https://jsonplaceholder.typicode.com/posts')    
    return data
}

function Posts(){
    const {data, error, isError, isLoading } = useQuery('posts', fetchPosts) 
    // first argument is a string to cache and track the query result
    if(isLoading){
        return <div>Loading...</div>
    }
    if(isError){
        return <div>Error! {error.message}</div>
    }

    return(
        <div className='container'>
        <h1>Posts</h1>
        {
            data.map((post, index) => {
                return <li key={index}>{post.title}</li>
            })
        }

        </div>
    )
}

export default Posts

React片段

React优化缓存实例教程:如果你是 React 开发人员,你可能遇到过一个错误,提示将组件与父 div 包装在一起。如果你的组件中不需要额外的 div,则添加它没有意义。例如,如果你的 React 应用程序中有 1000 个组件,那么你将有 1000 个额外的 div,这对 DOM 来说可能很重。为了避免这种情况,React 为你提供了使用片段的选项:

const Message = () => {
  return (
    <React.Fragment>
      <p>Hello<p/>
      <p>I have message for you<p/>
    </React.Fragment>
  );
};

下面的代码片段与上面的代码完全相同,<>用作React.Fragment的快捷方式:

const Message = () => {
  return (
    <>
      <p>Hello<p/>
      <p>I have message for you<p/>
    </>
  );
};

无论使用哪种方法,都可以避免添加额外的<div>,从而减少 DOM 标记、提高渲染性能并减少内存开销。

React虚拟列表

如何在React中优化缓存?通常,我们需要在浏览器上呈现大型列表;这样做对浏览器来说是很复杂的,因为它必须创建新节点并将它们全部绘制在屏幕上。

为了使 React 中的过程高效,我们可以选择使用虚拟列表。虚拟列表仅根据需要呈现少数项目,只需在用户动态滚动项目时替换它们。

渲染比更改 DOM 更快,因此你可以使用虚拟列表以快速的性能渲染数千个列表项。React-virtualized是一个优秀的库,它具有渲染虚拟列表的组件。

React优化缓存的方法:功能组件

React 从基于类的组件开始,但是,由于其轻量级的特性,现在建议使用函数式组件。功能组件基本上是创建速度更快的函数,并且它们更容易缩小,从而减小包的大小。

React优化缓存实例教程结论

在本教程中,我们介绍了几种用于优化 React 应用程序中缓存管理的不同解决方案,例如记忆、缓存选择器、延迟加载、React 片段、虚拟列表和功能组件。这些方法中的每一种都可以通过减少不必要的组件渲染数量、减少开销和提高速度来改进你的应用程序。

正确的解决方案将取决于你个人项目的需求,但希望本文能帮助你了解可用的选项。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: