Tips on retrieving and showcasing information from various endpoints in React?

I am working with two different endpoints and I need to fetch data from both simultaneously in order to display it in one single element. For example, I want to show data from one table along with the corresponding name from another table if the product id matches. Currently, my code for fetching data from one endpoint looks like this:

import React, {useState, useEffect} from 'react'
import products from '../apis/apiURLS'
import './Products.css';

const Products = () => {
    const [productInfo,setProductInfo] = useState([]);

    const fetchProducts  = async () =>{
        const response = await products.get('/products/')
        setProductInfo(response.data)
    }

    useEffect(()=>{
        fetchProducts()
    },[])

    return (
      <div>
      <h1 className = "header">Products</h1>      
      {productInfo.map(products=> {
        return (

      <div className="productInfo">
        {console.log(products)}
        <p>Date: {products.date}</p>

      </div>

      )

        
})}
</div>
    )}

export default Products

EDIT
The Products endpoint contains fields date and product_id, while the Stock endpoint has fields product_id and name, where product_id is the foreign key to Stock.
I have attempted to add another async function for the second endpoint:

const [stockInfo, setStockInfo] = useState([]);
const fetchStock  = async () =>{
      const response = await stock.get('/stock/')
      setStockInfo(response.data)
  }
    useEffect(()=>{
      fetchStock()
  },[])

However, I am having trouble properly mapping the data to display in a single element. My desired output is:

<p>Product: {stock.name}, {products.date}</p>

Answer №1

If you find that the outcomes of calling both APIs are interdependent, utilizing Promise.all can ensure successful completion of fetch requests for both endpoints.

Subsequently, you can merge the results by utilizing the product_id field and a single useState hook to store the combined data in the component state.

For instance,

const combineUsingProductIdField = (products, stocks) => {
  const keyByProductIdField = (previousValue, currentValue) => ({
    ...previousValue,
    [currentValue.product_id]: currentValue,
  });
  const stocksByProductId = stocks.reduce(keyByProductIdField, {});

  const productsWithStock = products.map(product => ({
    product,
    stock: stocksByProductId[item.product_id],
  }));
  return productsWithStock;
};

const Products = () => {
  const [productsWithStock, setProductsWithStock] = useState([]);

  const fetchProductsWithStock = () => {
    const fetchProducts = async () => {
      return await products.get('/products/');
    };
    const fetchStocks = async () => {
      return await stock.get('/stock/');
    };

    try {
      const [_products, _stocks] = await Promise.all([
        fetchProducts,
        fetchStocks,
      ]);
      setProductsWithStock(combineUsingProductIdField(products, stocks));
    } catch (err) {
      // log to error reporting;
    }
  };

  useEffect(() => {
    fetchProductsWithStock();
  }, []);

  return (
    <div>
      <h1 className="header">Products</h1>
      {productsWithStock.map(({ product, stock }) => {
        return (
          <div className="productInfo">
            <p>
              Product: {stock.name}, {product.date}
            </p>
          </div>
        );
      })}
    </div>
  );
};

export default Products;

If feasible, I suggest having a unified API endpoint that provides this amalgamated dataset. This approach allows you to leverage existing relationships defined in your data models to retrieve the stock information for each product.

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

Verify if the term is present in an external JSON file

I am currently using tag-it to allow users to create tags for their posts. At the moment, users can type any word, but I have a list of prohibited words stored in JSON format. I am looking for a way to integrate this list into the tagit plugin so that if ...

"Optimizing the Placement of jPlayer for Your Website

Struggling to properly position jPlayer on my webpage. After consulting jPlayer's documentation, I learned that it is supposed to be absolutely positioned by default. However, it seems to be flowing with the rest of the page content rather than being ...

Shared Vue configuration settings carrying over to Jest spec files

For my unit testing of components using VueJS and Jest, I'm incorporating the Bootstrap Vue library for styling. To address console warnings regarding unknown plugins, I've set up a configuration file: import { createLocalVue } from '@vue/t ...

Issue encountered when attempting to utilize Next-Auth alongside Credentials Provider to authenticate within a pre-existing system

I am currently utilizing the Next-Auth Credentials provider for authentication purposes through our existing API. Following the guidelines provided at https://next-auth.js.org/configuration/callbacks the code snippet used is as follows: callbacks: { ...

Anticipating the execution of pool.query within a callback function in the Express framework

Within an Express post endpoint, I am utilizing crypto.generateKeyPair. After generating the key pair, I wish to store it in my database and then return the ID of the inserted row within the same endpoint. Here is the code snippet for the endpoint: app.p ...

Switch app engines in real-time based on the URL path with express framework

How can I dynamically set App Engine based on the URL? In my application, I have two render engines available: serverSideRenderEngine & browserRenderEngine If the URL is /home, the app.engine should be set as serverSideRenderEngine If the URL is /l ...

Creating a dynamic header using react-virtuoso and material ui

I recently upgraded my table to a virtuoso table in order to improve loading time. However, I am facing issues with formatting the table properly. Previously, when it was just a material ui table, everything aligned perfectly. Despite reading through the d ...

Refresh cloned element after making changes to the original element

Just starting to explore Jquery and looking for some guidance to get me started :) Question: I'm facing an issue with a cart total price that is displayed in a different part of the page using clone(). I want this cloned price to automatically update ...

Inserting HTML content into a DIV with the help of jQuery

Looking for a solution with my index.html file. I want to load other HTML files into a DIV by clicking on buttons. Here's an example of what I'm trying to achieve: I've searched through various examples online, but none seem to work for ...

How to Deactivate the Default Selection in React-Select

Having trouble with the focus in a React Select dropdown. The first item always gets focused when opening the dropdown, despite passing various props without success. I checked their GitHub for related issues around autofocus but couldn't find a solut ...

Switching the body's background image dynamically using javascript

I'm attempting to switch up the background image using JavaScript. Here's how I've defined the background: body { background: black; overflow-x: hidden; overflow-y: hidden; } body:before { overflow-x: hidden; overflow ...

Identifying the HTML Hidden Attribute Using JavaScript Without Dependencies

As someone working in the analytics field, I often rely on CSS selectors to address various issues. Currently, I am faced with a task on a website where I need to determine whether a <p> element is hidden or visible. There are two possible scenarios: ...

What steps can I take to direct mobile visitors to the mobile-friendly version of my website?

Looking for a way to automatically redirect users on mobile devices from www.domain.com to the new mobile version at m.domain.com? ...

Error: ajax is not defined and needs to be declared (repeated twice)

Currently, I have a form that requires processing using Ajax. <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script> <div class="column1"> <form class="form box" action="javascript:networkCheck();" ...

Detecting Pixel Colors Across Multiple Overlapping Canvases

I have a challenge with multiple canvas elements on my webpage. I am trying to retrieve the pixel color of all overlapping canvas elements when they are stacked on top of each other. Let me illustrate with an example below. In this scenario, I am attempt ...

The header row in HTML tables sometimes vanishes unexpectedly after sorting the table

Upon filtering the table, I noticed that the header disappears sporadically. The issue is that the table header row should remain in place regardless of whether or not the characters used for filtering are present in the table rows. In Example 1: When fil ...

Pressing the button does not switch the component state (when the button and component are located in separate files)

Here is the code snippet of my layout: import Menu from "./Menu"; import ButtonMenu from "./ButtonMenu"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en" ...

Using Material UI with React and TypeScript

I need some assistance with organizing my menus correctly in React using TypeScript. Currently, they are displaying on top of each other instead of within their respective category menus. I have been struggling to find a solution and would appreciate any h ...

Maintain a fixed element and enable the rest of the elements to scroll as the mobile browser address bar collapses while scrolling upwards

Currently facing a challenge where I want the background image to remain static while the address bar and content underneath scroll up. The image occupies 90% of the view height, and although I've prevented it from resizing and jumping when the addres ...

Function defined as an AngularJS component

I am facing an issue where my component is not initializing when I create it with a function that returns a component object. Can someone please help me understand the difference between these two situations? Html: <div ng-app="demoApp"> <navb ...