用反应挂钩的措施(仅几秒钟的火力功能一次)



我需要在用户输入上实现标签搜索,但是输入很快,我不想为每个用户键入的每个符号发射db调用,所以我是curios,是否有一个简单的一个好方法来审阅API通话,请说 - 3秒后延迟一次后一次?

现在我想到了:

  let searchDelay
  async function handleTagSearch(e) {
    clearTimeout(searchDelay)
    tagSearchPhraseSet(e.target.value)
    searchDelay = setTimeout(async () => {
      if (e.target.value.length > 3) {
        let res = await fetch('api/tag_seatch/' + e.target.value)
        res = await res.json() 
        console.log(res)
      }
    }, 3000)
  }

但是它是正确的方法吗?

如果您确保searchDelay号码在使用中的渲染之间持续存在,则您的解决方案看起来很有希望。useRef钩。

进行操作的另一种方法是使用每次输入value更改时运行的useEffect挂钩。从给出的函数到useEffect,您可以返回清除以前运行的超时的函数。

示例

const { useState, useEffect } = React;
function App() {
  const [value, setValue] = useState("");
  const [result, setResult] = useState(null);
  useEffect(
    () => {
      if (value.length < 3) {
        setResult(null);
        return;
      }
      const timeout = setTimeout(() => {
        setResult(Math.random());
      }, 3000);
      return () => clearTimeout(timeout);
    },
    [value]
  );
  return (
    <div>
      <input value={value} onChange={e => setValue(e.target.value)} />
      <div>{result}</div>
    </div>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

感谢@tholle的示例,我知道qoute" qoute"从使用效率函数返回的函数将被调用 every time it is run again,然后按照您的说法进行删除,并提出了此解决方案:

import React, { useState, useContext, useEffect, useRef } from 'react'
export function TagsAdd() {
  const [searchTerm, searchTermSet] = useState('')
  const isFirstRun = useRef(true)
  useEffect(() => {
   //skip first run on component mount
   if (isFirstRun.current) {
      isFirstRun.current = false
      return
   }
    const timeout = setTimeout(() => {
      tagSearch(searchTerm)
    }, 2000) //2000 - timeout to execute this function if timeout will be not cleared
    return () => clearTimeout(timeout) //clear timeout (delete function execution)
  }, [searchTerm])
  // API call only one time in 2 seconds for the last value! Yeeeee
  async function tagSearch(value) {
    let res = await fetch('api/tag_seatch/' + value)
    res = await res.json()
    console.log(res)
  }
  //handle input change
  function handleInput(e) {
    searchTermSet(e.target.value)
  }
  return (
        <div>
          <input value={searchTerm} onChange={handleInput} />
        </div>
  )
}

您需要考虑的第一件事是使用 useCallback进行记忆,如果您只编写一个普通功能,它将在每个重新渲染上重新陈述。IMO您应该使用Lodash的debounce函数,而不是实现自己的功能。结果看起来像这样:

const searchTags = useCallback(debounce(async evt => {
  const { value } = evt.target;
  if(value.length > 3){
    const response = await fetch('/api/tag_search', value);
    const result = await response.json();
    setTags(result) //or somewhere in your state
  }
}, 3000, { trailing: true, leading: false }));

最新更新