简体   繁体   中英

redux state doesn't have updated value in InterSectionObserver callback function

I am using IntersectionObserver api for implementing infinite scroll. When callback is called,then inside the callback ,redux state does not have updated value.The functions are:

//function for defining InfiniteScroll
const InfiniteScroll = (parent,target,options,callback,getObject)=>{
    const Infoptions = {
        root: parent,
        rootMargin: '50px',
        threshold: 1.0,
        ...options
      }
      
      let observer = new IntersectionObserver(callback, Infoptions);
      observer.observe(target);      
      getObject(observer);
      
}


export default InfiniteScroll;


This function is used here:

//calling InfiniteScroll
    const target = useRef();
    const parent = useRef();
    const observer = useRef();
    const state = useSelector((state)=>state);

    useEffect(() => {
        if(!loading){
            
            InfiniteScroll(parent.current, target.current, {}, callbackScroll, function (obs) {
                observer.current = obs;
            })
        }
        return () => {
            observer.current&&observer.current.disconnect();
        }
    }, [loading])

    const callbackScroll = useCallback((data, observer) => {
        
        if (data[0].isIntersecting) {
            if ((state.post.data[postid]?.hasmorecomments) !== false){
                //if there are more comments ,then this function will call api to fetch comments
                FetchPostComments();
                //here (state.post.data[postid]) returns undefined value,
                //which is the initial value(when component has not mounted),
                //but in some_other function ,it returns updated value
                console.log((state.post.data[postid]));
            }
        }
    },[FetchPostComments])    
 

const some_other = ()=>{
   //here it logs expected value(an object,not undefined)
   console.log(state.post.data[postid]);
}

I want the updated value inside callbackScroll function just like the function some_other . How may i achieve it?

Edit-1: jsx code where target is being used

//parent is the reference to scrollable div   
return (
     <div ref={parent}>
           <Comments/>
           {//here too, state.post.data[postid] has updated value}
           {((state.post.data[postid]?.hasmorecomments) !== false)&&<Loader/>}
            <div ref={target}></div>
     </div>
)

The purpose of using a useCallback is to avoid unnecessary function invocation every time when a parent component or self is re-rendered, this is achieved by returning a memorized version of the callback function, that is invoked only when the state or reference value in the dependency array change. The function inside the useCallback is executed only once when the component is initially mounted with initial state values. Hence, it is returning undefined . You'd want it to execute again when the state is updated (ie invoke the function when the state is updated to contain more comments in this case). You can accomplish this by simply including the state in the dependency array of your useCallback hook.

const callbackScroll = useCallback((data, observer) => {
        
        if (data[0].isIntersecting) {
            if ((state.post.data[postid]?.hasmorecomments) !== false){
                //if there are more comments ,then this function will call api to fetch comments
                FetchPostComments();
                //here (state.post.data[postid]) returns undefined value,
                //which is the initial value(when component has not mounted),
                //but in some_other function ,it returns updated value
                console.log((state.post.data[postid]));
            }
        }
    },[FetchPostComments,state]) //Include state in dependency array

The problem was basically with dependency array of useEffect and useCallback

useEffect(() => {
        if(!loading){
            
            InfiniteScroll(parent.current, target.current, {}, callbackScroll, function (obs) {
                observer.current = obs;
            })
        }
        return () => {
            observer.current&&observer.current.disconnect();
        }
    }, [loading,parent,target,callbackScroll,observer])

const callbackScroll = useCallback((data, observer) => {
        
        if (data[0].isIntersecting) {
            if ((state.post.data[postid]?.hasmorecomments) !== false){
                //if there are more comments ,then this function will call api to fetch comments
                FetchPostComments();
                //here (state.post.data[postid]) returns undefined value,
                //which is the initial value(when component has not mounted),
                //but in some_other function ,it returns updated value
                console.log((state.post.data[postid]));
            }
        }
    },[FetchPostComments,state]) //Include state in dependency array

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM