簡體   English   中英

React JS setTimeout 被多次執行

[英]React JS setTimeout gets executed multiple times

大家好,我是 React JS 的新手,我陷入了一個無法弄清楚原因的問題。 因此,我正在嘗試制作一個僅在用戶完成輸入后才觸發 API 調用的搜索字段組件。 發生的事情是,在setTimeout中鍵入搜索后會執行多次。 恐怕這會造成多次不必要的 api 調用。 非常感謝您的幫助。 謝謝!

主要的.tsx

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <App />
)

應用程序.tsx

import { useState } from 'react'
import fetchData from './utils/fetch'
import { WeatherModel } from './model/Weather'

function SearchField() {
  let timer = 0
  const [city, setCity] = useState('New York')

  const handleFetchWeather = async () => {
    const data: WeatherModel = await fetchData(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${WEATHER_API_KEY}&units=metric`)
    console.log(data)
  }

  const handleSetCity = (e) => {
    if(timer) clearTimeout(timer)
    setCity(e.target.value)
    timer = setTimeout(() => {
      console.log(city)
      // handleFetchWeather()
    }, 2000)
  }

  return (
    <div className="search">
      <input type="text" placeholder="Search city..." onChange={handleSetCity} />
    </div>
  )
}

export default SearchField

鍵入搜索后的多個控制台日志在此處輸入圖像描述

您可以使用去抖動

這是一個例子:

useEffect(() => {
    let debounce;
    
    if (debounce) {
        clearTimeout(debounce);
        debounce = null;
    }

    debounce = setTimeout(() => {
        // DO SOMETHING AFTER TIMEOUT ENDS
        setSearchEntry(searchValue);
    }, 1 * 1000);
    
}, [setSearchEntry, searchValue]);

祝你好運 :)

我同意 debounce 解決方案,但如果你不知道,這段代碼對你來說可能更簡單,所以每次組件重新渲染時,計時器再次設置為 0,所以為了保持值,想象一下你需要把它放在一個狀態,就像這樣:

import { useState } from "react";

function SearchField() {
  const [city, setCity] = useState("New York");
  const [timer, setTimer] = useState(0);

  const handleFetchWeather = async () => {
    const data = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${WEATHER_API_KEY}&units=metric`
    );
    console.log(data);
  };

  const handleSetCity = (e) => {
    if (timer) {
      clearTimeout(timer);
    }
    setCity(e.target.value);
    setTimer(
      setTimeout(() => {
        console.log(city);
        // handleFetchWeather()
      }, 2000)
    );
  };

  return (
    <div className="search">
      <input
        type="text"
        placeholder="Search city..."
        onChange={handleSetCity}
      />
    </div>
  );
}

export default SearchField;

現在,每次重新渲染,組件都會記住它之前的值;)

輸入字段中的 onChange 事件將在每個新字符輸入時觸發,在此處了解更多信息。

我認為在這種情況下,最好的解決方案是添加觸發 handleSetCity() 的提交按鈕,並且您的 onChange 應該設置一個狀態變量,以便更容易處理數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM