在2020年提升React应用性能的10条技巧

There are different ways of solving the same problem when it comes to programming — whether it be JavaScript, React, Python, or any other language. When you look into someone else’s code, there is always something new that you can learn.

解决同一问题时,有多种解决方法,无论是JavaScript,React,Python还是任何其他语言。 当您查看别人的代码时,总会有一些新知识可以学习。

React is evolving day by day and there are various approaches that can be used to solve any problem that we face in our application. Let’s look at ten tips and tricks that will definitely help you while working with React. Think of these tricks mostly as performance boosters for your application.

React每天都在发展,可以使用各种方法来解决我们在应用程序中遇到的任何问题。 让我们看一下十个技巧和窍门,这些技巧和窍门绝对会在使用React时为您提供帮助。 这些技巧主要是为您的应用程序带来性能提升。

1.暂停控制台调试器 (1. Pause Console Debugger)

You have surely come across a scenario where you want to debug the style of dropdown or something else that closes automatically when you try to right-click on the element and click on “Inspect element.”

您肯定会遇到一种情况,当您尝试右键单击元素并单击“检查元素”时,您要调试下拉菜单的样式或其他会自动关闭的样式。

Here is a simple solution:

这是一个简单的解决方案:

  1. Open your console from a browser.

    从浏览器打开控制台。
  2. Type in the following command:

    输入以下命令:
setTimeout(() => {debugger;}, 5000)

3. Then open the dropdown that you want to debug.

3.然后打开要调试的下拉菜单。

ralex1993 ralex1993

2. useState的带函数的延迟初始化 (2. useState Lazy Initialization With Function)

There are times when we need to set the initial value of the state from some variable or from a function that returns a value.

有时候,我们需要从某些变量或返回值的函数中设置状态的初始值。

Let’s take a look at the example below:

让我们看下面的例子:

const initialState = someFunctionThatCaluclatesValue(props)const [count, setCount] = React.useState(initialState)

Since our function is in the body, every time a re-render happens, this function is getting called even if its value is not required (we only need it during the initial render).

由于我们的函数在主体中,因此每次重新渲染时都会调用此函数,即使不需要它的值也是如此(我们仅在初始渲染时需要它)。

Let’s see how to lazy initialize useState with a function:

让我们看看如何通过一个函数来延迟初始化useState

const getInitialState = (props) => someFunctionThatCaluclatesValue(props)const [count, setCount] = React.useState(getInitialState)

Creating a function is very fast. React will only call the function when it needs the initial value (which is when the component is initially rendered). So even if the function is taking a lot of time, it will be slow on the initial render only. This is called “lazy initialization.” It’s a performance optimization.

创建功能非常快。 React仅在需要初始值时(即组件最初被渲染时)才调用该函数。 因此,即使该功能花费大量时间,它也只会在初始渲染时变慢。 这称为“延迟初始化”。 这是性能优化。

Let’s look at this GIF to get an idea of what that looks like:

让我们看一下这个GIF,以大致了解一下:

Image for post
Lazy function vs. ordinary function
惰性函数与普通函数

To play around with the example above:

要玩上面的示例:

Example on CodeSandbox
CodeSandbox上的 示例

3.使用自定义挂钩 (3. Making Use of Custom Hooks)

With hooks, we don’t have some facility that can help us get the callback as in the case of setState.

对于钩子,我们没有像setState这样的设施可以帮助我们获取回调。

For example, we get the callback in the state. Once the state is set, we usually use the callback function:

例如,我们使回调处于状态。 设置状态后,我们通常使用回调函数:

this.setState({
"name" : "Harsh"
}, () => {
// Hey that state is set successfully what do you
// want to do, I'm callback your friend 😄
})

Let’s see how can we achieve similar behavior with a custom hook that gets called only when the state is changed and isn’t called during the initial render:

让我们看看如何使用自定义钩子实现类似的行为,该自定义钩子仅在状态更改时才被调用,而在初始渲染期间不被调用:

const App = () => {
  const [state, setState] = useStateCallback(0); // same API as useState + setState with cb


  const handleClick = () => {
    setState(
      prev => prev + 1,
      // 2nd argument is callback , `s` is *updated* state
      // Hey that state is set successfully what do you
      // want to do, I'm callback your friend 😄
      s => console.log("I am called after setState, state:", s)
    );
  };


  return <button onClick={handleClick}>Increment</button>;
}

For more easy-to-understand hook recipes, check out Gabe Ragland.

有关更多易于理解的钩子配方,请查看Gabe Ragland

4.监视应用程序中不必要的渲染 (4. Monitor Unnecessary Renders in Your Applications)

One of the common problems we face is evaluating the necessary renders in your application that are having a bad impact on the performance.

我们面临的常见问题之一是评估应用程序中必要的渲染,这些渲染会对性能产生不良影响。

There are different ways we can evaluate them to avoid unnecessary renders in minutes

我们可以通过多种方式评估它们,从而避免在几分钟内产生不必要的渲染

你为什么渲染 (why-did-you-render)

Image for post
GitHub. GitHub

According to its documentation, why-did-you-render “monkey patches React to notify you about avoidable re-renders.” This will display unnecessary renders that are happening in your application so that you can take action against them.

根据其文档, 为什么要渲染 “猴子补丁React以通知您有关可避免的重新渲染”。 这将显示应用程序中正在发生的不必要的渲染,以便您可以对它们采取措施。

React Devtools (React Devtools)

As noted by DebugBear:

DebugBear所述

“DevTools give us a visualization of the performance of your app. To see this, ensure that you are running React in development mode, open DevTools in your browser, and then go to the “Performance” tab.

“ DevTools为我们提供了您应用程序性能的可视化。 为此,请确保您在开发模式下运行React,在浏览器中打开DevTools,然后转到“性能”选项卡。

You can record the performance of your app from a point after the page has loaded or from the page load. There are two buttons in the top left corner of the DevTools dialog:”

您可以在页面加载后或页面加载后的某个时间记录应用程序的性能。 DevTools对话框的左上角有两个按钮:”

Image for post
Start recording
开始录音

Once you stop recording, you will be able to see a graph showing different components that rendered and the time taken to render them.

停止记录后,您将可以看到一个图形,其中显示了渲染的不同组件以及渲染它们所花费的时间。

Image for post
Rendering information
渲染信息

5.使用React.memo和useMemo (5. Using React.memo and useMemo)

According to React's official documentation:

根据React的官方文档

"React.memo is a higher-order component.

React.memo是一个高阶组件。

If your function component renders the same result given the same props, you can wrap it in a call to React. In some cases, memoizing the result will provide a performance boost. This means that React will skip rendering the component and reuse the last rendered result.”

如果您的函数组件在使用相同的道具时呈现相同的结果,则可以将其包装在对React的调用中。 在某些情况下,记住结果可以提高性能。 这意味着React将跳过渲染组件并重用最后渲染的结果。”

React.memo does a shallow comparison out of the box and avoids rendering. A Stack Overflow user defined a shallow comparison as being “when the properties of the objects being compared are done using === or strict equality and will not conduct comparisons deeper into the properties.”

React.memo了较浅的比较,并避免了渲染。 Stack Overflow用户将浅表比较定义为“当使用===或严格等于完成比较对象的属性时,不会在属性中进行更深入的比较。”

Image for post
This will result in re-rendering.
这将导致重新渲染。

Note: In the example above, true means that the component will render again despite the values being the same.

注意:在上面的示例中, true 表示即使值相同,组件也将再次呈现。

But there are times when you need to do a deep comparison, meaning you want to compare the nested properties in an array of objects. How can we do that? Let’s jump into our next trick.

但是有时您需要进行深度比较,这意味着您想比较对象数组中的嵌套属性。 我们该怎么做? 让我们跳入下一个技巧。

6. shouldComponentUpdate中的深​​度比较 (6. Deep Comparison in shouldComponentUpdate)

As we saw in the example above, React.memo can only help you to avoid re-rendering if your values are simple. But if you have a nested array of objects, you cannot compare them right out of the box.

正如我们在上面的示例中看到的那样,如果您的值很简单, React.memo只能帮助您避免重新渲染。 但是,如果您有嵌套的对象数组,则无法立即比较它们。

Use deep-equal:

使用深度相等:

Compare two objects and return whether they are equal according to a recursive equality algorithm.

比较两个对象并根据递归相等算法返回它们是否相等。

“If opts.strict is true, use strict equality (===) to compare leaf nodes. The default is to use coercive equality (==) because that's how assert.deepEqual() works by default.” — deep-equal

“如果opts.stricttrue ,请使用严格相等( === )比较叶节点。 默认是使用强制相等( == ),因为这就是assert.deepEqual()默认工作的方式。” — 深平等

Note: There are many such packages that can help you compare two nested arrays of objects to avoid re-rendering via comparison.

注意:有很多这样的软件包可以帮助您比较两个嵌套的对象数组,以避免通过比较重新呈现。

7.React窗口 (7. React Window)

Since most of the application has to do with rendering the data in the form of a list, when the list grows long, it’s like a poison is slowly entering your application and having a bad impact on the performance. It starts consuming a lot of memory in the browser as well. Since all the list items are in the DOM, there is a lag when you scroll the list.

由于大多数应用程序都与以列表形式呈现数据有关,因此当列表长时,就好像有毒物质缓慢进入您的应用程序,并对性能造成不良影响。 它也开始消耗浏览器中的大量内存。 由于所有列表项都在DOM中,因此滚动列表时会有滞后。

How can we render only some parts of the items on the list that are currently visible on the screen then? Make use of React Window:

我们如何只呈现列表中当前在屏幕上可见的项目的某些部分呢? 利用React Window:

No matter the size of your list (e.g. 1,000 items), it will only display 20–30 items in the DOM depending on the size of your window, which is completely customizable and will boost performance!

无论列表的大小(例如1,000个项目)如何,它都将根据窗口的大小在DOM中仅显示20–30个项目,这是完全可自定义的,将提高性能!

8.React查询 (8. React Query)

With hooks for fetching, caching, and updating asynchronous data in React, managing server state is easier than ever before with React Query.

借助用于在React中获取,缓存和更新异步数据的钩子,使用React Query管理服务器状态比以往任何时候都更加容易。

Here are the features listed on GitHub:

以下是GitHub上列出的功能:

  • Transport/protocol/back-end agnostic data fetching (REST, GraphQL, promises, whatever!)

    传输/协议/后端不可知数据获取(REST,GraphQL,promise等)!
  • Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)

    自动缓存+重新获取(重新验证时有效,窗口重新聚焦,轮询/实时)
  • Parallel + Dependent Queries

    并行+从属查询
  • Mutations + Reactive Query Refetching

    变异+React性查询重新提取
  • Multi-layer Cache + Automatic Garbage Collection

    多层缓存+自动垃圾收集
  • Paginated + Cursor-based Queries

    分页+基于游标的查询
  • Load-More + Infinite Scroll Queries w/ Scroll Recovery

    带有滚动恢复的更多加载+无限滚动查询
  • Request Cancellation

    取消请求
  • React Suspense + Fetch-As-You-Render Query Prefetching

    React Suspense +按需获取查询预取

  • Dedicated Devtools (React Query Devtools)

    专用Devtools(React Query Devtools)

GitHub. GitHub的示例。

9.延迟加载React组件(带有React.lazy和Suspense) (9. Lazy Loading React Components (With React.lazy and Suspense))

什么是React.lazy()? (What is React.lazy( )?)

As written by Nwose Lotanna, React.lazy is:

正如Nwose Lotanna所写React.lazy是:

“A new function in React that lets you load React components lazily through code splitting without help from any additional libraries. Lazy loading is the technique of rendering only needed or critical user interface items first, then quietly unrolling the non-critical items later.”

“ React中的新功能,可让您通过代码拆分延迟加载React组件,而无需任何其他库的帮助。 延迟加载是先呈现仅需要或关键的用户界面项目,然后再安静地展开非关键项目的技术。”

什么是悬念? (What is Suspense?)

"Suspense is a component required by the lazy function that is basically used to wrap lazy components. Multiple lazy components can be wrapped with the help of the Suspense component. It also takes a fallback property that is going to accept the React elements you want to render as the lazy component is being loaded.” — Nwose Lotanna

Suspense是lazy函数所需的组件,基本上是用来包装lazy组件的。可以通过Suspense组件来包装多个lazy组件。它还具有一个fallback属性,该属性将接受您想要的React元素。在加载惰性组件时呈现。” — Nwose Lotanna

See the code to play around with this on CodeSandbox.

CodeSandbox上查看代码以解决此问题。

You can now identify any large components on a page in your application that only render on certain user interactions (like clicking a button, toggle, etc). Splitting these components will minimize your JavaScript payloads and help you increase performance.

现在,您可以在应用程序页面中标识仅在某些用户交互(例如单击按钮,切换等)时呈现的任何大型组件。 拆分这些组件将最大程度地减少JavaScript负载,并帮助您提高性能。

10.一种更新多个输入状态值的函数 (10. One Function to Update Multiple Input State Values)

This is the common use case of keeping the same function to update multiple input values. Most of us know about this approach that helps to reduce the code and get our job done. This is useful in case there are multiple inputs in a form:

这是保持相同功能以更新多个输入值的常见用例。 我们大多数人都知道这种方法,可以帮助减少代码并完成工作。 如果表单中有多个输入,这很有用:

import React from "react";


function Form() {
  const [state, setState] = React.useState({
    firstName: "",
    lastName: ""
  })
  
  // same function can be used to update multiple values in the state
  const handleChange = (evt) => {
    const value = evt.target.value;
    setState({
      ...state,
      [evt.target.name]: value
    });
  }
  return (
    <form>
      <label>
        First name
        <input
          type="text"
          name="firstName"
          value={state.firstName}
          onChange={handleChange}
        />
      </label>
      <label>
        Last name
        <input
          type="text"
          name="lastName"
          value={state.lastName}
          onChange={handleChange}
        />
      </label>
    </form>
  );
}

结论 (Conclusion)

Did you know any of these tricks? Thanks for reading this article. I hope you learned something new!

您知道这些技巧吗? 感谢您阅读本文。 希望您学到新知识!

翻译自: https://medium.com/better-programming/10-tips-and-tricks-to-boost-your-react-apps-performance-in-2020-9388159f6ebf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值