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

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进行debouncethrottle

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值