PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Sunday, July 31, 2022

[FIXED] How do I asynchronously update a variable from a paginated API using React hooks?

 July 31, 2022     pagination, react-hooks, reactjs     No comments   

Issue

I'm currently trying to fetch all of the properties for an object from an API, and display them in a table. The API will return up to 10 results at a time, and will return a value nextPageToken in the response body if there are more results to be fetched. My goal is to fetch the first 10 results, immediately display them in the table, and add to the table as I continue to hit the API. This was my first attempt at a solution:

const getProperties = async (id) => {
  const properties = await Api.getProperties(id);
  setProperties(properties.properties);
  if (properties.nextPageToken) loadMoreProperties(id, nextPageToken);
};

const loadMoreProperties = async (id, nextPageToken) => {
  const properties = await Api.getProperties(id, nextPageToken);
  setProperties(prevProperties => {return [...prevProperties, properties.properties]});
  if (properties.nextPageToken) loadMoreProperties(id, properties.nextPageToken);
};

(Note that the above is a simplification; in practice, there's more logic in getProperties that doesn't need to be repeated on subsequent calls to the API)

The problem that I'm running into with this solution is that when I'm calling loadMoreProperties, the setProperties call isn't yet finished. How can I enforce that the call to loadMoreProperties only happens after setting the previous set of properties? Is there an overall better pattern that I can follow to solve this problem?


Solution

You can use useEffect to trigger the page loads as a reaction to a completed state change:

const [page, setPage] = useState(); // will be {properties, nextPageToken}

// load first page whenever the id changes
useEffect(() => {
     Api.getProperties(id)
       .then(page => setPage(page)));
  }, [id]);

// load next page (if there is one) - but only after the state changes were processed
useEffect(() => {
    if (page?.nextPageToken == null) return;
    Api.getProperties(id, page.nextPageToken)
       .then(page => setPage(page)));
  }, [id, page]
);

// this will trigger the re-render with every newly loaded page
useEffect(()=> setProperties(prev => [...(prev || []), page.properties]), [page]);

The first effect will cause an update to the state variable page.

Only after the state change is completed, the second effect will be triggered and initiate the fetch of the second page.

In parallel, the third effect will perform the changes to the state variable properties, that your table component depends on, after each successful page load and page state update, triggering a re-render after each update.



Answered By - Steffen Frank
Answer Checked By - Marilyn (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing