Skip to content

πŸš€ Backend connection - fetching and sending data πŸš€

Notifications You must be signed in to change notification settings

ch0ripain/react-sending-http-requests

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

33 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ§™β€β™‚οΈ Sending HTTP Requests πŸ§™β€β™‚οΈ

1. Initial Fetch Approach βš™οΈ

useEffect(() => {
  fetch("http://localhost:3000/places")
    .then((response) => response.json())
    .then((responseData) => setAvailablePlaces(responseData.places));
}, []);
  • Basic fetch nested with .then() callbacks.
  • This approach works but can become hard to read and maintain.

2. Improved: Using async/await and Loading State πŸš€

const [availablePlaces, setAvailablePlaces] = useState([]);
const [isFetchingData, setIsFetchingData] = useState(false);

useEffect(() => {
  async function fetchPlaces() {
    setIsFetchingData(true);
    const response = await fetch("http://localhost:3000/places");
    const responseData = await response.json();
    setAvailablePlaces(responseData.places);
    setIsFetchingData(false);
  }
  fetchPlaces();
}, []);
  • Replaced .then() with an async function.
  • Added a loading state (isFetchingData) to show feedback to the user while fetching.

Note

An async function declaration creates an AsyncFunction object. Each time when an async function is called, it returns a new Promise which will be resolved with the value returned by the async function, or rejected with an exception uncaught within the async function.

3. Error Handling with try/catch πŸ›‘οΈ

const [availablePlaces, setAvailablePlaces] = useState([]);
const [isFetchingData, setIsFetchingData] = useState(false);
const [error, setError] = useState();

useEffect(() => {
  async function fetchPlaces() {
    try {
      setIsFetchingData(true);
      const response = await fetch("http://localhost:3000/places");
      const responseData = await response.json();

      if (!response.ok) {
        throw new Error("Fetching data error :(");
      }

      setAvailablePlaces(responseData.places);
    } catch (error) {
      setError(
        error.message ||
          "Could not fetch the places data, please try again later."
      );
    }
    setIsFetchingData(false);
  }
  fetchPlaces();
}, []);
  • Added error handling using a try/catch block.
  • Included an error state to manage and display errors.

4. Final Optimization: Outsourcing HTTP Logic 🧰

Moved the HTTP request logic to a standalone utility function http.js for cleaner and more reusable code.

export async function fetchAvailablePlaces() {
  const response = await fetch("http://localhost:3000/places");
  const responseData = await response.json();
  if (!response.ok) {
    throw new Error("Error fetching places data.");
  }
  return responseData.places;
}

//final example code
import { fetchAvailablePlaces } from "../http.js";

async function fetchPlaces() {
  try {
    setIsFetchingData(true);
    const places = await fetchAvailablePlaces();
    setAvailablePlaces(places);
  } catch (error) {
    setError(error.message || "Failed to fetch places.");
  }
  setIsFetchingData(false);
}

Making HTTP Requests with Methods, Body, and Headers πŸš€

By default, fetch uses the GET method. If you want to use a different HTTP method, you need to provide an options object with specific properties such as method, body, and headers.

This function sends an HTTP PUT request to update user places on the server.

export async function updateUserPlaces(places) {
  const response = await fetch("http://localhost:3000/user-places", {
    method: "PUT", // Specify the HTTP method
    body: JSON.stringify({ places }), // Convert JS object to JSON format
    headers: {
      "Content-Type": "application/json", // Inform the server about the data type
    },
  });

  const responseData = await response.json(); // Parse the response body as JSON

  if (!response.ok) {
    throw new Error("Updating user places went wrong :("); // Handle errors
  }

  return responseData.message; // Return a success message
}

Explanation of Key Concepts 🧰


Common HTTP Methods 🌐

GET ➑️ Retrieve data from the server
POST ➑️ Send new data to the server
PUT ➑️ Update existing data on the server
DELETE ➑️ Remove data from the server
PATCH ➑️ Partially update data


body: JSON.stringify({ places })

  • JSON.stringify() converts a JavaScript object into a JSON-formatted string because HTTP requests require plain text (not raw JS objects).
  • You must pass an object with key-value pairs (e.g., { places: [...] }) so the server can properly identify and handle the data.

headers: { "Content-Type": "application/json" }

  • The headers property defines additional information sent with the request.
  • Content-Type: application/json tells the server that the body contains JSON-formatted data, ensuring it is parsed correctly.

response.json()

  • The .json() method reads the server's response body and converts it into a JavaScript object.
  • This is necessary because fetch returns a stream by default, and you need to "decode" it into usable data.

🐸 This project is a practice exercise I learned from the Academind's React Course 🐸