取消功能

问题描述 投票:0回答:1

我在搜索页面上有一个组件,在该组件内部,有一个 useEffect ,当搜索词(城市、帖子中的单词、帖子数量)发生变化时,会触发帖子过滤并从数据库中获取代码。当我输入一个单词然后将其删除时,代码会继续运行。如果我输入另一个单词,这两个函数基本上是并行运行的。我想这样做,以便当输入或添加新单词时,先前的过滤过程将被重置并重新开始。例如,如果我输入一个单词并且代码开始(开始迭代并过滤帖子),然后我立即删除该单词并添加另一个单词,则正在进行的代码将停止并以新条件重新开始。

React.useEffect(() =>  {
    const loadAndFilterPosts = async () => {
        let postsToLoad = 300; // first count posts for loading
        let allLoadedPosts:any = []; // array for all loading posts
        let filteredPosts= [];
        let keys:string[] = []; // keys from redis
        let i = 0;

      // if chosen category => get keys from refdis
      if (chosenCategory && chosenCategory.id) keys = await getKeys(chosenCategory?.id)

      while (allLoadedPosts.length < postsToLoad) {
          let newPosts = await loadPostsFromRedis(i, keys); // loading posts from Redis
          if (!newPosts.length) {
              break;
          }

          // if free period 
          if (infoUser && infoUser?.categoriesFreePeriod?.length > 0 && !infoUser?.endFreePeriod) {
              const currentDate = new Date();
              currentDate.setDate(currentDate.getDate() - 3);
              newPosts = newPosts.filter((item: any) => new Date(item.post_date_publish*1000).getTime() < currentDate.getTime());
          }

          allLoadedPosts = [...allLoadedPosts, ...newPosts];
          filteredPosts = applyFilters(allLoadedPosts); // add filter (keywords)

          setFilteredPosts(filteredPosts.sort((a:any, b:any) => a.data - b.data))
          if (filteredPosts.length >= postsToLoad) {
              break;
          }

          postsToLoad += 300;
          i++;
       }
   };
    loadAndFilterPosts()
    setPage(1)
}, [keyWords, keyCityWords, social, postsCount, chosenCategory])
javascript reactjs
1个回答
0
投票

您描述的过程称为

debouncing
。您可以使用
underscore
lodash
提供的实用程序,但这里是一个自定义示例:

const runDebouncedSearch = useMemo(
  () => debounce((term: string) => searchSomething(term), 400),
  []
);

useEffect(() => {
  runDebouncedSearch(inputSearchTerm); // when input changes, schedule search in 400 ms. Cancel previous searches if typing rapidly
  return () => runDebouncedSearch.cancel(); // cancel pending searches, when detaching component
}, [runDebouncedSearch, inputSearchTerm]);

和实施:

type DebounceOptions = XOR<
  { leading?: boolean },
  { leadingOnce?: boolean }
>;

export const debounce = <A = void>(
  func: (arg: A) => void,
  delay: number,
  { leading, leadingOnce }: DebounceOptions = {}
): CancellableFunction<A> => {
  let timerId: NodeJS.Timeout | undefined;
  let isLeadingRan = false;

  const debounced = (arg: A) => {
    const shouldRunLeadingOnce = leadingOnce && !isLeadingRan;
    const shouldRunLeading = leading || shouldRunLeadingOnce;

    if (!timerId && shouldRunLeading) {
      isLeadingRan = true;
      func(arg);
    }
    if (timerId) {
      clearTimeout(timerId);
    }

    timerId = shouldRunLeadingOnce
      ? undefined
      : setTimeout(() => func(arg), delay);
  };

  debounced.cancel = () => {
    timerId && clearTimeout(timerId);
    timerId = undefined;
  };

  return debounced;
};
© www.soinside.com 2019 - 2024. All rights reserved.