ReactJS: After Adding the Chrome CORS Plugin, Unhandled Rejection (TypeError) Failed to Fetch

Temp mail SuperHeros
ReactJS: After Adding the Chrome CORS Plugin, Unhandled Rejection (TypeError) Failed to Fetch
ReactJS: After Adding the Chrome CORS Plugin, Unhandled Rejection (TypeError) Failed to Fetch

Handling API Errors in React: CORS Plugin Challenges

When working with APIs in ReactJS, developers often encounter various challenges related to data fetching, especially when dealing with third-party APIs. One common issue that arises is the "Unhandled Rejection (TypeError): Failed to fetch" error. This error can occur even when using popular APIs like Swiggy’s restaurant list API, which many developers use to enhance their web applications.

In this case, adding a CORS Chrome extension might seem like a viable solution to bypass restrictive browser policies. However, it may introduce new complications instead of resolving the issue. If you're using a CORS plugin in your development environment, and your API requests fail shortly after loading, you could be running into a problem where the plugin conflicts with the browser's request-handling behavior.

Understanding how to manage cross-origin requests and troubleshoot CORS errors in ReactJS is essential for a smooth development process. APIs like Swiggy's often have security layers, such as CORS, in place to control access from unauthorized clients. These restrictions can lead to errors that need to be addressed properly.

In this guide, we’ll explore why this error occurs, particularly after adding a CORS plugin in Chrome. We’ll also discuss strategies to resolve it while working with the Swiggy API in your React applications.

Command Example of use
fetch() This command is used to make HTTP requests to the Swiggy API. It fetches resources asynchronously and returns a promise, which resolves to a Response object. It is key for retrieving restaurant data from the API.
useEffect() Used in React, this hook allows the execution of side effects like API calls after rendering the component. It ensures that the fetch request to Swiggy's API is made once the component is mounted.
res.setHeader() This Express command sets custom HTTP headers, such as Access-Control-Allow-Origin, which is crucial in CORS handling. It enables the backend to allow requests from any origin, preventing CORS errors.
res.json() This method is used to send a JSON response back to the client. In the proxy server solution, it ensures the API data fetched from Swiggy is returned as JSON format, which the front end can easily consume.
await This keyword pauses the execution of the asynchronous function until the fetch operation resolves, ensuring the code waits for the API's data before proceeding, preventing unhandled rejections.
express() The express() function is used to create an instance of an Express server. This server acts as a proxy between the frontend and the Swiggy API to prevent CORS issues during data fetching.
app.listen() This command makes the Express server start listening for incoming requests on a specified port (e.g., port 5000 in this case). It is crucial for hosting the proxy server locally during development.
try...catch This block handles errors that may occur during the fetch request, such as network failures or issues with the Swiggy API. It ensures that the app gracefully handles errors instead of crashing.

Explaining Solutions for CORS Issues in React with Swiggy API

In the first solution, we created a Node.js backend using Express to bypass the CORS issue when fetching the restaurant data from Swiggy’s API. The CORS policy prevents browsers from making requests to a different domain unless that domain permits it. By creating a simple server, we can act as a middle layer between the client and the API, fetching the data server-side and returning it to the React front-end. This method avoids CORS errors since the request comes from the same origin as the client app.

The Express backend sets up custom headers, particularly the Access-Control-Allow-Origin, which allows our client to request the resources without facing CORS restrictions. The fetch call to Swiggy's API is made server-side, and the data is returned in JSON format. This approach is often considered more secure and performant in production environments since it hides API keys or sensitive information. Furthermore, the use of try-catch ensures proper error handling, displaying user-friendly error messages if the API fails to respond.

In the second solution, we modify the fetch request on the client-side React code. This method involves adding custom headers in the fetch call, ensuring that the request is correctly formatted before reaching the API. We use React's useEffect hook to trigger the API call when the component mounts. The async function waits for the API response, converts it to JSON, and handles errors if the request fails. However, this solution still faces CORS issues if the API does not allow cross-origin requests from browsers directly.

Finally, in the third solution, we use a third-party service called CORS-Anywhere. This is a middleware service that temporarily helps bypass CORS restrictions by rerouting the API request through their server. While this solution can work in development environments, it is not recommended for production due to security risks and the dependency on external services. It also introduces performance overhead as it adds an additional layer to the data fetching process. Using this method can be convenient during testing phases but should be avoided in production for security reasons.

Solution 1: Handling CORS Issues with Proxy Server

This solution uses a Node.js backend proxy server to avoid CORS errors and correctly fetch data from the Swiggy API.

const express = require('express');
const fetch = require('node-fetch');
const app = express();
const port = 5000;

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET');
  next();
});

app.get('/restaurants', async (req, res) => {
  try {
    const response = await fetch('https://www.swiggy.com/dapi/restaurants/list/v5?lat=23.1685786&lng=79.9338798');
    const data = await response.json();
    res.json(data);
  } catch (err) {
    res.status(500).json({ error: 'Failed to fetch restaurants' });
  }
});

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});

Solution 2: Using Front-End Fetch with Custom Headers and Error Handling

This approach modifies the fetch request directly in React, adding custom headers and handling errors effectively.

import React, { useEffect } from 'react';

const Body = () => {
  async function getRestaurants() {
    try {
      const response = await fetch(
        'https://www.swiggy.com/dapi/restaurants/list/v5?lat=23.1685786&lng=79.9338798',
        { headers: { 'Content-Type': 'application/json' } }
      );

      if (!response.ok) {
        throw new Error('Network response was not ok');
      }

      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error('Fetch error:', error);
    }
  }

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

export default Body;

Solution 3: Using CORS-Anywhere Middleware for Development

This method uses the "CORS-Anywhere" service to bypass CORS restrictions while in development mode. This solution should not be used in production.

const Body = () => {
  async function getRestaurants() {
    try {
      const response = await fetch(
        'https://cors-anywhere.herokuapp.com/https://www.swiggy.com/dapi/restaurants/list/v5?lat=23.1685786&lng=79.9338798'
      );

      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error('Error fetching restaurants:', error);
    }
  }

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

export default Body;

Troubleshooting CORS Issues in API Requests

One of the underlying reasons for the "Failed to fetch" error in a React application, especially when using third-party APIs like Swiggy, is CORS (Cross-Origin Resource Sharing) restrictions. CORS is a security feature that restricts web applications from making requests to a different domain than the one from which they were served. In this case, the Swiggy API rejects the request because it originates from a different domain (your React app). This is particularly problematic when you are fetching data from APIs that don’t explicitly support cross-origin requests.

A common workaround is using browser extensions like the "Allow CORS" Chrome extension. However, such extensions can lead to inconsistent results. This is because they manipulate browser-level settings that don’t always synchronize properly with API requests. These plugins should ideally be used only for development and not in production environments. For production, a safer and more reliable approach would be using a backend proxy server that requests the data on behalf of your React app, as seen in the solutions provided earlier.

Another aspect to consider is handling errors effectively. While CORS issues are a common cause of "Failed to fetch" errors, other factors like network instability, incorrect API URLs, or server downtime could also result in this error. Hence, it’s important to implement robust error handling in your code, especially when working with third-party APIs. A proper error-handling mechanism will help debug the issue more effectively and provide user-friendly messages when something goes wrong.

Common Questions About CORS and API Requests in React

  1. What is CORS and why is it important?
  2. CORS (Cross-Origin Resource Sharing) is a security policy enforced by browsers to prevent malicious requests from untrusted domains. It ensures that only certain domains are allowed to fetch resources from a server.
  3. Why am I getting "Unhandled Rejection (TypeError): Failed to fetch"?
  4. This error typically occurs when your API request is blocked due to CORS restrictions. It may also be caused by incorrect API URLs or issues with the server.
  5. What does the useEffect hook do in this context?
  6. The useEffect hook in React is used to trigger an API request after the component is mounted. It ensures that the fetch operation occurs at the right time, preventing multiple unnecessary requests.
  7. How can I fix CORS errors in a React application?
  8. To fix CORS errors, you can use a backend proxy, set proper headers with res.setHeader in the server, or rely on services like CORS-Anywhere for development purposes.
  9. Can I use CORS browser extensions in production?
  10. No, CORS browser extensions should only be used for development. In production, it’s safer to configure CORS on the server or use a proxy server.

Final Thoughts on Managing CORS Errors in React

CORS errors are a common challenge when developing React applications that consume third-party APIs. Although browser extensions can help in development, it is critical to implement more reliable solutions like a proxy server in production environments to maintain security and data integrity.

By using the right techniques, such as error handling and backend solutions, developers can efficiently handle issues like "Failed to fetch." This ensures that their application provides a smooth user experience when interacting with APIs, enhancing performance and functionality.

References and Source Material for Understanding CORS Issues in React
  1. For detailed information on Cross-Origin Resource Sharing (CORS) and how to manage it in React, refer to MDN Web Docs on CORS .
  2. To understand more about common React errors like "Failed to fetch" and potential solutions, check React Documentation on Error Boundaries .
  3. If you're working with Express for setting up a proxy server to bypass CORS issues, visit Express.js Routing and Middleware .
  4. For help on how to work with the Fetch API in JavaScript, see MDN Web Docs on Fetch API .
  5. Explore how to use Swiggy’s API for restaurant data in the official API documentation: Swiggy API .