You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useCallback钩子内部的回调函数具体在什么时候执行?

无限滚动加载实现中useCallback包裹的回调函数执行时机疑问

以下是无限滚动加载的相关代码:
代码主要包含两个部分:MainComponent组件和一个自定义hook组件。每次在搜索框输入内容时会发送请求并将数据展示在页面上,MainComponent中使用lastElementRef为最后一个元素绑定Intersection Observer API,实现滚动到页面底部时自动发送下一页请求。

我不清楚传入useCallback(()=>{})中的函数具体什么时候会执行,为了统计它的执行次数,我在MainComponent的第21行添加了console.log打印日志。
希望社区的朋友可以帮忙解答这个问题,非常感谢。

我已经搜索过相关资料、观看了不少讲解useCallback的视频,目前仅了解到useCallback仅会在其依赖数组中的依赖项发生变化时返回新的函数对象,否则每次组件重渲染时都会返回被缓存的函数。我将相关代码分享如下:
请求发送使用axios实现。

MainComponent 代码

//MainComponent
import React,{useState,useRef,useCallback} from 'react'
import useBookSearch from './useBookSearch';

export default function MainComponent() {
    
    //these 2 stataes are here because 
    //we want them to be used in this component only
    //meaning we dont want them to be part 
    //of any custom logic 

    const[query,setQuery] = useState('');
    const[pageNumber,setPageNumber] = useState(1);
    const observer = useRef();
     

    const  {books,loading,hasMore,error} = useBookSearch(query,pageNumber);
    
     
    const lastElementRef = useCallback(node=>{

        console.log("How many times did i run ?");

        if(loading) return ;

        if(observer.current) observer.current.disconnect();
        observer.current = new IntersectionObserver(entries=>{
          if(entries[0].isIntersecting && hasMore){
              setPageNumber(prevPage => prevPage + 1);
          }

        })
        if(node) observer.current.observe(node);
        console.log(node);
    },[loading,hasMore])


    const handleSearch=(e)=>{

      setQuery(e.target.value);
      setPageNumber(1);

    }

  

    return (
        <div>

            <input  value={query} type="text" onChange={handleSearch} ></input>
            {books.map((book,index) =>{
                if(books.length === index + 1)
                {
                return <div ref={lastElementRef}key={book}>{book}</div>

                }
                else{
                  return <div key={book}>{book}</div>  
                }
            })}
            {loading && 'Loading.....................'}
            {error && 'Error........'}
            

        </div>
    )
}

自定义hook useBookSearch 代码

import { useEffect,useState } from 'react';
import axios from 'axios'
export default function useBookSearch(query,pageNumber) {
    const[loading,setLoading] = useState('true');
    const[error,setError] = useState('false');
    const[books,setBooks] = useState([]);
    const[hasMore,setHasMore] = useState(false);

    //second useEffect which clear the books first 
    //and then make an api request

    useEffect(()=>{
      setBooks([]);
    },[query])

    useEffect(()=>{
        setLoading(true);
        setError(false);
        let cancel ;
       axios({
           method:'GET',
           url:'http://openlibrary.org/search.json',
           params:{q:query,page:pageNumber},
           cancelToken:new axios.CancelToken(c=>cancel=c)
       }).then(res=>{
           setBooks(prevBooks=>{
               return [...new Set([...prevBooks,...res.data.docs.map(b=>b.title)])]
           })
           setHasMore(res.data.docs.length > 0);
           setLoading(false);
           console.log(res.data);
       }).catch(e=>{

            if(axios.isCancel(e)) return
            setError(true); 
         })

       return ()=> cancel();
    },[query,pageNumber])  
    return {loading,error,books,hasMore};
}

运行效果截图

输入字符串test拉取数据时的控制台窗口截图:
输入test时的控制台窗口截图


内容的提问来源于stack exchange,提问作者Rohan Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 03:54:01