如何使用钩子消除功能组件中的回调 [英] How to debounce a callback in functional component using hooks

查看:40
本文介绍了如何使用钩子消除功能组件中的回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 React 功能组件去抖动回调中获得实际的 prop 值,它在 React 类组件中工作,但我不知道如何使用钩子在功能组件中实现这种行为.

从react"导入React;从react-dom"导入 ReactDOM;从lodash.debounce"导入去抖动;const TestFunc = ({ count, onClick }) =>{const handleClick = debounce(() => {点击();控制台日志(计数);}, 500);返回 (<div><button type="button" onClick={handleClick}>函数:{count}

);};class TestClass 扩展了 React.Component {handleClick = debounce(() => {this.props.onClick();console.log(this.props.count);}, 500);使成为() {返回 (<div><button type="button" onClick={this.handleClick}>课程:{this.props.count}

);}}const App = () =>{const [countClass, setCountClass] = React.useState(0);const [countFunc, setCountFunc] = React.useState(0);返回 (<div><TestFunc count={countFunc} onClick={() =>setCountFunc(countFunc + 1)}/><测试类计数={countClass}onClick={() =>setCountClass(countClass + 1)}/>

);};ReactDOM.render(, document.getElementById("root"));

当你点击功能组件按钮时,它会将之前的 count 属性值记录到控制台,但它已经通过调用 onClick 处理程序改变了,同时类组件按钮将在 onClick 处理程序增加后记录实际的 count 属性值.那么,如何在功能组件中获取实际的 prop 值?

解决方案

这是一个简单的 debounce hook(用 TypeScript 编写)

import { useEffect, useRef } from "react";导出函数 useDebouncedCallback(回调: (...args: A) =>空白,等待:数量){//跟踪参数 &调用之间的超时句柄const argsRef = useRef();const timeout = useRef>();功能清理(){如果(超时.当前){clearTimeout(timeout.current);}}//确保我们的超时被清除,如果//我们的消费组件被卸载useEffect(() => 清理,[]);返回函数 debouncedCallback(...参数:A){//捕获最新的参数argsRef.current = args;//清除去抖动定时器清理(​​);//再次开始等待timeout.current = setTimeout(() => {如果(argsRef.current){回调(...argsRef.current);}}, 等待);};}

您的用例示例:

const handleClick = useDebouncedCallback(() => {点击();控制台日志(计数);}, 500);...<button type="button" onClick={handleClick}>函数:{count}

也适用于传递参数的情况:

const handleChange = useDebouncedCallback((event) => {console.log(event.currentTarget.value);}, 500);<input onChange={handleChange}/>

How can I get actual prop values in React Functional Component debounced callbacks, It worked in React Class Component, but I have no idea how to reach this behavior in functional component using hooks.

import React from "react";
import ReactDOM from "react-dom";
import debounce from "lodash.debounce";

const TestFunc = ({ count, onClick }) => {
  const handleClick = debounce(() => {
    onClick();
    console.log(count);
  }, 500);

  return (
    <div>
      <button type="button" onClick={handleClick}>
        Func: {count}
      </button>
    </div>
  );
};

class TestClass extends React.Component {
  handleClick = debounce(() => {
    this.props.onClick();
    console.log(this.props.count);
  }, 500);

  render() {
    return (
      <div>
        <button type="button" onClick={this.handleClick}>
          Class: {this.props.count}
        </button>
      </div>
    );
  }
}

const App = () => {
  const [countClass, setCountClass] = React.useState(0);
  const [countFunc, setCountFunc] = React.useState(0);

  return (
    <div>
      <TestFunc count={countFunc} onClick={() => setCountFunc(countFunc + 1)} />
      <TestClass
        count={countClass}
        onClick={() => setCountClass(countClass + 1)}
      />
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

When you click on functional component button, it logs the previous count prop value to console, but it's already changed by calling onClick handler, in the same time the class component button would log the actual count prop value after it was incremented by onClick handler. So, how can I get actual prop values in functional component?

Here's a simple debounce hook (written in TypeScript)

import { useEffect, useRef } from "react";

export function useDebouncedCallback<A extends any[]>(
  callback: (...args: A) => void,
  wait: number
) {
  // track args & timeout handle between calls
  const argsRef = useRef<A>();
  const timeout = useRef<ReturnType<typeof setTimeout>>();

  function cleanup() {
    if(timeout.current) {
      clearTimeout(timeout.current);
    }
  }

  // make sure our timeout gets cleared if
  // our consuming component gets unmounted
  useEffect(() => cleanup, []);

  return function debouncedCallback(
    ...args: A
  ) {
    // capture latest args
    argsRef.current = args;

    // clear debounce timer
    cleanup();

    // start waiting again
    timeout.current = setTimeout(() => {
      if(argsRef.current) {
        callback(...argsRef.current);
      }
    }, wait);
  };
}

Example for your use case:

const handleClick = useDebouncedCallback(() => {
  onClick();
  console.log(count);
}, 500);

... 

<button type="button" onClick={handleClick}>
  Func: {count}
</button>

Also works for cases that pass arguments:

const handleChange = useDebouncedCallback((event) => {
  console.log(event.currentTarget.value);
}, 500);

<input onChange={handleChange}/>

这篇关于如何使用钩子消除功能组件中的回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆