猿问

将参数传递给函数回调

我正在尝试在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


弑天下
浏览 172回答 2
2回答

蓝山帝景

lodash debounce 将函数作为第一个参数。您可以简单地用作函数,并在调用时传递给该函数,然后将其传递给fetchDatasearchValuedebounceLoadDatafetchDataconst debounceLoadData = useCallback(debounce(fetchData, 1000), []);&nbsp; useEffect(() => {&nbsp; &nbsp; debounceLoadData(searchValue);&nbsp; &nbsp; console.log({searchValue})&nbsp; }, [searchValue]);debounce实际上返回一个函数,认为deboounce是像这样实现的function debounce(func, wait) {&nbsp; let timeout&nbsp; return function(...args) {&nbsp; &nbsp; const context = this&nbsp; &nbsp; clearTimeout(timeout)&nbsp; &nbsp; timeout = setTimeout(() => func.apply(context, args), wait)&nbsp; }}所以基本上是这里返回的函数,然后被传递给原始函数 fetchData,就像debounceLoadDataarguments passed to it i.e ...argsfunc.apply(context, args)也只创建一次,因为回调依赖关系是,你传递它使用Effect作为不依赖关系不会有任何区别。debounceLoadData[]请阅读这篇文章,了解缺少依赖关系警告

largeQ

我从不喜欢,这是一个非常令人困惑的钩子,我总是使用,因为它完全涵盖了可以做的事情(但不是相反)。useCallbackuseMemouseCallbackfunction SearchBar() {&nbsp; const [searchValue, setSearchValue] = useState("");&nbsp; const handleSearchFieldChange = ((value:string) => {&nbsp; &nbsp; setSearchValue(value);&nbsp; });&nbsp; const debounceLoadData = useMemo(() => debounce(fetchData, 1000), []);&nbsp; /**&nbsp; &nbsp;* the equivalent of useCallback should be:&nbsp; &nbsp;*&nbsp; &nbsp;* const debounceLoadData = useCallback(debounce(fetchData, 1000), []);&nbsp; &nbsp;*&nbsp;&nbsp; &nbsp;* But I really advice against it!&nbsp; &nbsp;* There's unnecessary function invocation compared to useMemo.&nbsp; &nbsp;*/&nbsp; useEffect(() => {&nbsp; &nbsp; debounceLoadData(searchValue);&nbsp; // <- you should pass in arg&nbsp; &nbsp; console.log({searchValue})&nbsp; }, [searchValue]);&nbsp; // ...}然而,对于您的情况,我不认为使用lodash debounce是最好的解决方案。存在一个隐藏的风险,即在卸载组件后,将最终调用 effect。如果包含某些状态突变逻辑,则会引发错误“无法在未挂载的组件上调用 setState(或 forceUpdate)”,这不会造成破坏性,但也不是最佳的。fetchDatafetchData我建议使用手动去抖动调用。这很简单:setTimeout/clearTimeoutuseEffect(() => {&nbsp; const timeoutId = setTimeout(() => fetchData(searchValue), 1000)&nbsp; return () => clearTimeout(timeoutId)}, [searchValue])
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答