Leveraging React Hooks' useEffect to trigger a prop callback function defined with useCallback

Currently, I am working on developing a versatile infinite scrolling feature using React Hooks along with the ResearchGate React Intersection Observer. The main concept revolves around a parent passing down a mapped JSX array of data and a callback function responsible for fetching more data asynchronously. Once the intersection observer detects that the user has scrolled to reveal the loading icon, it triggers the callback which fetches additional data.

This implementation is functioning adequately, except for one issue: esLint warns me about calling the getMore function (from props) within a useEffect, necessitating it to be a dependency of that effect. However, since the callback in the parent accesses the length of its data array, that array needs to be a dependency of useCallback. Consequently, this callback then modifies the array.

To summarize, I am encountering race conditions leading to multiple asynchronous callback triggers due to changes in the callback function reference being passed down to the caller component unintentionally.

Below is some code snippet for clarification:

The callback in the parent component:

const loadData = useCallback(async () => {
    if (hasMore) {
        const startAmount = posts.length;
        for (let i = 0; i < 20; ++i) {
            posts.push(`I am post number ${i + startAmount}.`);
            await delay(100);
        }
        setPosts([...posts]);
        setHasMore(posts.length < 100);
    }
}, [posts, hasMore]);

The posts and hasMore variables are simply state variables, where posts is passed down as the data array in props to the child component. This function is then passed to the child via props, with the following setup (getMore is the deconstructed prop for the callback, while isLoading is a boolean state variable):

useEffect(() => {
    if (isLoading) {
        (async () => {
            await getMore();
            setIsLoading(false);
        })();
    }
}, [isLoading, getMore]);

I utilize setting isLoading to true to activate the effect; however, it is also triggered by changes in the getMore reference when the parent loads new data causing function memoization. This behavior should not occur. Although I could disable esLint for that specific line, I believe there might be a more optimal solution that I am unaware of and would appreciate some insights on it.

Answer №1

Solution: To improve efficiency, consider bypassing the use of useEffect altogether. Instead, directly invoke the loading function from the observer and have it update the isLoading state and trigger the callback without relying on isLoading to initiate the callback.

const loadData = async (observerEntry) => {
    if (observerEntry.isIntersecting && !disabled && !isLoading) {
        setIsLoading(true);
        await getMore();
        setIsLoading(false);
    }
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Locate a specific class inside a div and switch the CSS style to hide one element and reveal another

I have two divs, each containing a span. By default, the display of each span class is set to none. My goal is to toggle the display property of the span within the clicked div. If the span is already visible, I want to hide it; if it's hidden, I want ...

Retrieve a targeted table from a webpage through Ajax refresh

On a webpage, I have a table that has two different views: simple and collapsible. I want to be able to toggle between these views using a button click without the need to refresh the entire page. Below is the code snippet I am currently using: $(&apo ...

Implementing React and Firebase Firestore V9 for Paginating to the Initial Page after Navigating Back

I've hit a roadblock here. Despite following the exact steps outlined in various posts and tutorials, I'm still stuck. I know the importance of using a cursor to set the first and last visible document for moving forward or backwards. When moving ...

To enable RTL in TextField, please note that the JssProvider is only available in "react-jss/src/JssProvider" and not in "react-jss/lib/JssProvider"

Seeking help to convert LTR to RTL in the following code: <TextField id="date" label="EmployeeDate" type="date" onChange= ...

Is there a way to confirm if the target has been successfully removed from the element using jQuery?

$(".dropdown-toggle").click(function(event) { var target = $(event.target); if (target.is(this)) { $(this).find(".caret").toggleClass("customcaret"); } }); <div class="dropdown-toggle"> <div class="caret"></div> </div> ...

Using JavaScript and HTML, showcase the capital city of a country along with its corresponding continent

As a newcomer to this platform, I am excited to share a code snippet that I have created using HTML and JavaScript. The code generates a textbox in an HTML page where users can type the name of a country. Upon inputting the country's name, the code dy ...

issue retrieving data from live website created with next.js

Hello, I've exhausted all possible avenues to identify the cause of the error occurring on my live website built with NEXTJS. I have observed that this error only occurs when I reload the website. It's worth noting that I can successfully login ...

What is the formula to determine if x is greater than y and also less than z?

I need help determining if a number falls within the range of greater than 0 but less than 8 using JavaScript. Can anyone assist me with this? Here is my attempt at it: if (score > 0 && score < 8) { alert(score); } ...

Issue with UseState causing a re-render not to be triggered

My orders list state works perfectly on the initial update. However, when an order in the database gets updated, the order list is updated but fails to trigger a re-render even with <...> const [orders, setOrders] = useState([]); useEffect(( ...

How can a borderless text field be created using Material UI?

Today, I delved into using Material UI for my React project. My goal is to create a registration form similar to this one. Essentially, I want 5 input text fields without any borders and with a simple background color effect when active. However, I'm ...

Having trouble with the onLoadingComplete props in the Next.js Image component?

Is there a way to properly retrieve the naturalWidth and naturalHeight using the onLoadingComplete props? I tried following the documentation on https://nextjs.org/docs/api-reference/next/image#onloadingcomplete but it doesn't seem to be working. Am I ...

Upgrade your development stack from angular 2 with webpack 1 to angular 6 with webpack 4

Recently, I have made the transition from Angular 2 and Webpack 1 to Angular 6 and Webpack 4. However, I am facing challenges finding the best dependencies for this new setup. Does anyone have any suggestions for the best dependencies to use with Angular ...

Javascript issue: opening mail client causes page to lose focus

Looking for a solution! I'm dealing with an iPad app that runs html5 pages... one specific page requires an email to be sent which triggers the Mail program using this code var mailLink = 'mailto:' + recipientEmail +'?subject=PDFs ...

Error: Trying to assign a value to a null property

I am facing an issue while trying to dynamically create "iframe's textarea" and insert the value of a variable. Unfortunately, I keep encountering an error. Any suggestions on how to resolve this problem? P.S: Using Google Chrome as the browser ...

Guide to substituting the index value with the user's specific choice

Let's simplify this. Suppose I have a list in my ng-repeat 1. A & index[0]<br> 2. B & index[1]<br> 3. C & index[2]<br> 4. D & index[3]<br><br> and there is an input field where the user can priorit ...

Encountering a Next.js 404 Error while Attempting to Reach a Page

Encountering a 404 error while trying to access a page in my Next.js project despite following guidance from documentation and online resources. The setup is as follows: The structure of my Next.js project is: my-nextjs-project/ app/ profile.js project ...

Instructions on inserting a new row beneath a selected row using jQuery

https://i.stack.imgur.com/AlwHm.png When the second column is clicked, the method below is called: function getListOfList(primaryId, isFlat, col) { alert(primaryId) $.ajax({ url : ("/" + serverURL + "/dataGrid/getChilds"), ...

Having issues with the link page in react-router-dom?

Currently, I am utilizing the react-router-dom library to manage routers. However, I have encountered an issue where linking to another page does not change the page, but instead adds the new page right after the previous one as shown in the image below. W ...

Why is it that my JQuery sliders appear perfectly fine when viewed locally, but fail to show up when accessed on

I'm facing an issue with two JQuery sliders on my page. The local version works fine, but when I upload it to my web host, only one slider functions correctly. I need both of them to work as intended. Any insights on how to resolve this problem? See ...

What steps can I take to resolve the CSP errors I am experiencing?

I am currently working with NextJs@12 and I am attempting to set up CSP for my application. Unfortunately, I keep encountering errors in my console and I cannot figure out where I am going wrong. Below is the current policy that I have in my next.config fi ...