如何在React中使用async/await语法与debounce函数?

huangapple go评论73阅读模式
英文:

How to use async/await syntax with the debunce function in react?

问题

以下是您要翻译的代码部分:

const { useState, useMemo } = React;

function debounce(fn, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn.apply(this, ...args), delay);
  }
}

const getApi = (terms) => `https://www.reddit.com/search.json?q=${terms}`;
const Search = () => {
  const DELAY = 500;
  const [text, setText] = useState("");
  const [list, setList] = useState([]);

  const fetchData = useMemo(debounce(async(evt) => {
    const res = await fetch(getApi(evt.target.value));
    const {data} = await res.json();
    setList(data.children.map(d => d.data.title));
  }, DELAY), []);

  return (
    <div>
      <form className="bg-gray-200 p-5">
        <input
          type="text"
          name="text"
          placeholder="search users..."
          value={text}
          onChange={(e) => {
            setText(e.target.value);
            fetchData(e);
            }
          }
          className="bg-white p-2 w-3/4 outline-none"
        />
      </form>
      <ul>
        {list.map(title => <li>{title}</li>)}
      </ul>
    </div>
  );
};

ReactDOM.render(<Search />, document.getElementById("app"));

希望这能帮助您解决问题。如果您有任何其他问题,请随时提出。

英文:

Trying to create an react autocomplete component and use debounce function to reduce frequent api call. The code is following:

const { useState, useMemo } = React;

function debounce(fn, delay) {
  let timeoutId;
  return (...args) =&gt; {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() =&gt; fn.apply(this, ...args), delay);
  }
}

const getApi = (terms) =&gt; `https://www.reddit.com/search.json?q=${terms}`;
const Search = () =&gt; {
  const DELAY = 500;
  const [text, setText] = useState(&quot;&quot;);
  const [list, setList] = useState([]);

  const fetchData = useMemo(debounce(async(evt) =&gt; {
    const res = await fetch(getApi(evt.target.value));
    const {data} = await res.json();
    setList(data.children.map(d =&gt; d.data.title));
  }, DELAY), []);

  return (
    &lt;div&gt;
      &lt;form className=&quot;bg-gray-200 p-5&quot;&gt;
        &lt;input
          type=&quot;text&quot;
          name=&quot;text&quot;
          placeholder=&quot;search users...&quot;
          value={text}
          onChange={(e) =&gt; {
            setText(e.target.value);
            fetchData(e);
            }
          }
          className=&quot;bg-white p-2 w-3/4 outline-none&quot;
        /&gt;
      &lt;/form&gt;
      &lt;ul&gt;
        {list.map(title =&gt; &lt;li&gt;{title}&lt;/li&gt;)}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};

ReactDOM.render(&lt;Search /&gt;, document.getElementById(&quot;app&quot;));

The api call has not been made after I test it from console. Any idea where goes wrong?

答案1

得分: 0

以下是代码部分的翻译:

The signature of useMemo is

const memoizedValue = useMemo(functionThatCreatesMemoizedValue, [dependencies]);

The first argument passed to it is executed immediately. But you have

const fetchData = useMemo(debounce(......), []);

debounce returns a debounced function; that debounced function is then called immediately by useMemo, and the return value is put into fetchData.

What you need to do is have a function that returns the debounced function.

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

For a memoized value that's a callback, you can also consider using useCallback instead, which works nearly identically but is arguably a bit more semantically appropriate.

const fetchData = useCallback(debounce((evt) => {
    console.log('api call');
}, DELAY), []);

希望对您有所帮助。

英文:

The signature of useMemo is

const memoizedValue = useMemo(functionThatCreatesMemoizedValue, [dependencies]);

The first argument passed to it is executed immediately. But you have

const fetchData = useMemo(debounce(......), []);

debounce returns a debounced function; that debounced function is then called immediately by useMemo, and the return value is put into fetchData.

What you need to do is have a function that returns the debounced function.

const fetchData = useMemo(() =&gt; debounce(......), []);

<!-- begin snippet: js hide: true console: true babel: true -->

<!-- language: lang-js -->

function debounce(fn, delay) {
let timeoutId;
return (...args) =&gt; {
clearTimeout(timeoutId);
timeoutId = setTimeout(() =&gt; fn.apply(this, ...args), delay);
}
}
const Search = () =&gt; {
const DELAY = 500;
const [text, setText] = React.useState(&quot;&quot;);
const [list, setList] = React.useState([]);
const fetchData = React.useMemo(() =&gt; debounce((evt) =&gt; {
console.log(&#39;api call&#39;);
}, DELAY), []);
return (
&lt;div&gt;
&lt;form className=&quot;bg-gray-200 p-5&quot;&gt;
&lt;input
type=&quot;text&quot;
name=&quot;text&quot;
placeholder=&quot;search users...&quot;
value={text}
onChange={(e) =&gt; {
setText(e.target.value);
fetchData(e);
}
}
className=&quot;bg-white p-2 w-3/4 outline-none&quot;
/&gt;
&lt;/form&gt;
&lt;ul&gt;
{list.map(title =&gt; &lt;li&gt;{title}&lt;/li&gt;)}
&lt;/ul&gt;
&lt;/div&gt;
);
};
ReactDOM.createRoot(document.querySelector(&#39;.react&#39;)).render(&lt;Search /&gt;);

<!-- language: lang-html -->

&lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.development.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.development.js&quot;&gt;&lt;/script&gt;
&lt;div class=&#39;react&#39;&gt;&lt;/div&gt;

<!-- end snippet -->

For a memoized value that's a callback, you can also consider using useCallback instead, which works nearly identically but is arguably a bit more semantically appropriate.

const fetchData = useCallback(debounce((evt) =&gt; {
console.log(&#39;api call&#39;);
}, DELAY), []);

<!-- begin snippet: js hide: true console: true babel: true -->

<!-- language: lang-js -->

function debounce(fn, delay) {
let timeoutId;
return (...args) =&gt; {
clearTimeout(timeoutId);
timeoutId = setTimeout(() =&gt; fn.apply(this, ...args), delay);
}
}
const Search = () =&gt; {
const DELAY = 500;
const [text, setText] = React.useState(&quot;&quot;);
const [list, setList] = React.useState([]);
const fetchData = React.useCallback(debounce((evt) =&gt; {
console.log(&#39;api call&#39;);
}, DELAY), []);
return (
&lt;div&gt;
&lt;form className=&quot;bg-gray-200 p-5&quot;&gt;
&lt;input
type=&quot;text&quot;
name=&quot;text&quot;
placeholder=&quot;search users...&quot;
value={text}
onChange={(e) =&gt; {
setText(e.target.value);
fetchData(e);
}
}
className=&quot;bg-white p-2 w-3/4 outline-none&quot;
/&gt;
&lt;/form&gt;
&lt;ul&gt;
{list.map(title =&gt; &lt;li&gt;{title}&lt;/li&gt;)}
&lt;/ul&gt;
&lt;/div&gt;
);
};
ReactDOM.createRoot(document.querySelector(&#39;.react&#39;)).render(&lt;Search /&gt;);

<!-- language: lang-html -->

&lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.development.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.development.js&quot;&gt;&lt;/script&gt;
&lt;div class=&#39;react&#39;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月8日 10:59:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75381004.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定