为了账号安全,请及时绑定邮箱和手机立即绑定

将参数传递给函数回调

将参数传递给函数回调

弑天下 2022-08-04 09:49:52
我正在尝试在lodash中使用debbounce来延迟onChange,请参阅下面的代码。import React, { useState, useEffect, useCallback } from "react";import { TopBar } from "@shopify/polaris";import { debounce } from "lodash";function SearchBar() {  const [searchValue, setSearchValue] = useState("");  const handleSearchFieldChange = ((value:string) => {    setSearchValue(value);  });  const debounceLoadData = useCallback(debounce({searchValue} => fetchData, 1000), []);  useEffect(() => {    debounceLoadData();    console.log({searchValue})  }, [searchValue]);  function fetchData(value:string) {    console.log("searchValue " + value);  }  const searchFieldMarkup = (    <TopBar.SearchField      onChange={handleSearchFieldChange}      value={searchValue}      placeholder="Search Value"    />  );  return <TopBar searchField={searchFieldMarkup} />;}一开始,我正在努力在fetchData函数中使用,但似乎由于范围,它无法读取它,尽管状态已更新,但它始终是空的。searchValue因此,我试图从 中传递它,但我不知道我该如何做到这一点,因为在 useCallback 中是一个函数调用。我怎么能进入里面.debounceLoadDatasearchValuefetchDatadebounce
查看完整描述

2 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

lodash debounce 将函数作为第一个参数。您可以简单地用作函数,并在调用时传递给该函数,然后将其传递给fetchDatasearchValuedebounceLoadDatafetchData


const debounceLoadData = useCallback(debounce(fetchData, 1000), []);


  useEffect(() => {

    debounceLoadData(searchValue);

    console.log({searchValue})

  }, [searchValue]);

debounce实际上返回一个函数,认为deboounce是像这样实现的


function debounce(func, wait) {

  let timeout

  return function(...args) {

    const context = this

    clearTimeout(timeout)

    timeout = setTimeout(() => func.apply(context, args), wait)

  }

}

所以基本上是这里返回的函数,然后被传递给原始函数 fetchData,就像debounceLoadDataarguments passed to it i.e ...argsfunc.apply(context, args)


也只创建一次,因为回调依赖关系是,你传递它使用Effect作为不依赖关系不会有任何区别。debounceLoadData[]


请阅读这篇文章,了解缺少依赖关系警告


查看完整回答
反对 回复 2022-08-04
?
largeQ

TA贡献2039条经验 获得超7个赞

我从不喜欢,这是一个非常令人困惑的钩子,我总是使用,因为它完全涵盖了可以做的事情(但不是相反)。useCallbackuseMemouseCallback


function SearchBar() {

  const [searchValue, setSearchValue] = useState("");


  const handleSearchFieldChange = ((value:string) => {

    setSearchValue(value);

  });


  const debounceLoadData = useMemo(() => debounce(fetchData, 1000), []);

  /**

   * the equivalent of useCallback should be:

   *

   * const debounceLoadData = useCallback(debounce(fetchData, 1000), []);

   * 

   * But I really advice against it!

   * There's unnecessary function invocation compared to useMemo.

   */



  useEffect(() => {

    debounceLoadData(searchValue);  // <- you should pass in arg

    console.log({searchValue})

  }, [searchValue]);


  // ...

}

然而,对于您的情况,我不认为使用lodash debounce是最好的解决方案。


存在一个隐藏的风险,即在卸载组件后,将最终调用 effect。如果包含某些状态突变逻辑,则会引发错误“无法在未挂载的组件上调用 setState(或 forceUpdate)”,这不会造成破坏性,但也不是最佳的。fetchDatafetchData


我建议使用手动去抖动调用。这很简单:setTimeout/clearTimeout


useEffect(() => {

  const timeoutId = setTimeout(() => fetchData(searchValue), 1000)

  return () => clearTimeout(timeoutId)

}, [searchValue])


查看完整回答
反对 回复 2022-08-04
  • 2 回答
  • 0 关注
  • 150 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号