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拉取数据时的控制台窗口截图:
内容的提问来源于stack exchange,提问作者Rohan Sharma
相关产品推荐
相关产品推荐

