您的位置:首页 > Web前端 > React

react 使用hook_如何在React中使用Debounce和Throttle并将其抽象为Hook

2020-08-20 17:14 2136 查看

react 使用hook

Hooks are a brilliant addition to React. They simplify a lot of logic that previously had to be split up into different lifecycles with

class
components.

钩子是React的绝佳补充。 它们简化了许多以前必须通过

class
组件拆分为不同生命周期的逻辑。

They do, however, require a different mental model, especially for first-timers.

但是,他们确实需要不同的思维模式, 尤其是对于初学者

I also recorded a short video series on this article which you may find helpful.

我还在本文上录制了一个简短的视频系列 ,您可能会有所帮助。

防抖和油门 (Debounce and throttle)

There are a ton of blog posts written about debounce and throttle so I won't be diving into how to write your own debounce and throttle. For brevity, consider

debounce
and
throttle
from Lodash.

有大量关于防抖和节流的博客文章,因此我不会深入研究如何编写自己的防抖和节流。 为简便起见,请考虑从Lodash进行

debounce
throttle

If you need a quick refresher, both accept a (callback) function and a delay in milliseconds (say

x
) and then both return another function with some special behavior:

如果需要快速刷新,则都接受一个(回调)函数和一个毫秒级延迟 (例如

x
),然后都返回另一个具有某些特殊行为的函数:

  • debounce
    : returns a function that can be called any number of times (possibly in quick successions) but will only invoke the callback after waiting for
    x
    ms from the last call.

    debounce
    :返回一个可以多次调用的函数(可能是快速连续调用),但是仅在等待上次调用
    x
    ms 之后才调用回调。

  • throttle
    : returns a function that can be called any number of times (possibly in quick succession) but will only invoke the callback at most once every
    x
    ms.

    throttle
    :返回可以多次调用的函数(可能是快速连续调用),但每
    x
    ms最多只能调用一次回调。

用例 (Usecase)

We have a minimal blog editor (here's the GitHub repo) and we would like to save the blog post to the database 1 second after the user stops typing.

我们有一个最小的博客编辑器(这是GitHub repo ),并且我们希望在用户停止键入后1秒钟将博客文章保存到数据库中。

You may also refer to this Codesandbox if you wish to see the final version of the code.

如果您希望查看代码的最终版本,则也可以参考此Codesandbox

A minimal version of our editor looks like this:

我们的编辑器的最低版本如下所示:

import React, { useState } from 'react';
import debounce from 'lodash.debounce';

function App() {
const [value, setValue] = useState('');
const [dbValue, saveToDb] = useState(''); // would be an API call normally

const handleChange = event => {
setValue(event.target.value);
};

return (
<main>
<h1>Blog</h1>
<textarea value={value} onChange={handleChange} rows={5} cols={50} />
<section className="panels">
<div>
<h2>Editor (Client)</h2>
{value}
</div>
<div>
<h2>Saved (DB)</h2>
{dbValue}
</div>
</section>
</main>
);
}

Here,

saveToDb
would actually be an API call to the backend. To keep things simple, I'm saving it in state and then rendering as
dbValue
.

在这里,

saveToDb
实际上是对后端的API调用。 为了简单
dbValue
,我将其保存为state,然后呈现为
dbValue

Since we only want to perform this save operation once user has stopped typing (after 1 second), this should be debounced.

因为我们只希望,一旦用户停止输入(1秒后)保存操作执行此,本应去抖 。

Here's the starter code repo and branch.

这是入门代码存储库和分支。

创建一个去抖动功能 (Creating a debounced function)

First of all, we need a debounced function that wraps the call to

saveToDb
:

首先,我们需要一个去抖动的函数来包装对

saveToDb
的调用:

import React, { useState } from 'react';
import debounce from 'lodash.debounce';

function App() {
const [value, setValue] = useState('');
const [dbValue, saveToDb] = useState(''); // would be an API call normally

const handleChange = event => {
const { value: nextValue } = event.target;
setValue(nextValue);
// highlight-starts
const debouncedSave = debounce(() => saveToDb(nextValue), 1000);
debouncedSave();
// highlight-ends
};

return <main>{/* Same as before */}</main>;
}

But, this doesn't actually work because the function

debouncedSave
is created fresh on each
handleChange
call. This will end up debouncing each keystroke rather than debouncing the entire input value.

但是,由于该功能,这实际上并不工作

debouncedSave
创建每个新
handleChange
通话。 这样最终会消除每个按键,而不是消除整个输入值。

useCallback (useCallback)

useCallback
is commonly used for performance optimizations when passing callbacks to child components. But we can use its constraint of memoizing a callback function to ensure the
debouncedSave
references the same debounced function across renders.

将回调传递给子组件时,

useCallback
通常用于性能优化。 但是,我们可以使用它的记忆一个回调函数的约束,以确保该
debouncedSave
引用同去抖功能跨越渲染。

I also wrote this article here on freeCodeCamp if you wish to understand the basics of memoization.

如果您希望了解记忆的基础知识,我也在freeCodeCamp上写了这篇文章

This works as expected:

这按预期工作:

import React, { useState, useCallback } from 'react';
import debounce from 'lodash.debounce';

function App() {
const [value, setValue] = useState('');
const [dbValue, saveToDb] = useState(''); // would be an API call normally

// highlight-starts
const debouncedSave = useCallback(
debounce(nextValue => saveToDb(nextValue), 1000),
[], // will be created only once initially
);
// highlight-ends

const handleChange = event => {
const { value: nextValue } = event.target;
setValue(nextValue);
// Even though handleChange is created on each render and executed
// it references the same debouncedSave that was created initially
debouncedSave(nextValue);
};

return <main>{/* Same as before */}</main>;
}

useRef (useRef)

useRef
gives us a mutable object whose
current
property refers to the passed initial value. If we don't change it manually, the value will persist for the entire lifetime of the component.

useRef
为我们提供了一个可变对象,其
current
属性引用传递的初始值。 如果我们不手动更改它,则该值将在组件的整个生命周期内保持不变。

This is similar to class instance properties (i.e. defining methods and properties on

this
).

这类似于类实例的属性(即,限定上的方法和属性

this
)。

This also works as expected:

这也可以按预期工作:

import React, { useState, useRef } from 'react';
import debounce from 'lodash.debounce';

function App() {
const [value, setValue] = useState('');
const [dbValue, saveToDb] = useState(''); // would be an API call normally

// This remains same across renders
// highlight-starts
const debouncedSave = useRef(debounce(nextValue => saveToDb(nextValue), 1000))
.current;
// highlight-ends

const handleChange = event => {
const { value: nextValue } = event.target;
setValue(nextValue);
// Even though handleChange is created on each render and executed
// it references the same debouncedSave that was created initially
debouncedSave(nextValue);
};

return <main>{/* Same as before */}</main>;
}

Continue reading on my blog for how to abstract these concepts into custom hooks or check out the video series.

继续在我的博客上阅读有关如何将这些概念抽象为自定义钩子的内容,或查看视频系列

You may also follow me on Twitter to stay updated on my latest posts. I hope you found this post helpful. :)

您也可以在Twitter上关注我,以了解我的最新帖子。 希望这篇文章对您有所帮助。 :)

翻译自: https://www.freecodecamp.org/news/debounce-and-throttle-in-react-with-hooks/

react 使用hook

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: