Search code examples
reactjsreact-state-management

Trying to set a state equal to data from axios fetch. Can console.log the data object but don't understand how to set to a state variable correctly?


I have built a simple URL scraper that grabs Open Graph data from a url. I am trying to save the data to a state variable so that I can render in a few different ways and maybe save it to a users profile. The app grabs the OpenGraph information successful and I can log this data object to the console. However, when I call setState(data) or setState({data}) the state does not update. I think it has something to do with the order of my function (when I try to update the state) but I am fairly new to React and I am not sure what I need to change.

Thanks in advance - code below:

import React from "react";
import axios from "axios";
import { useState } from "react";

export default function UrlCrawler() {
  const [openGraphData, setOpenGraphData] = useState();

  window.onload = () => {
    const urlForm = document.getElementById("urlForm");
    const url = document.getElementById("url");
    const result = document.getElementById("result");
    const copyToClipboard = document.getElementById("copyToClipboard");

    urlForm.addEventListener("submit", (event) => {
      event.preventDefault();
      axios({
        url: `http://localhost:3000/scrape`,
        method: "POST",
        data: {
          url: url.value,
        },
      }).then(({ data }) => {
        setOpenGraphData(data);
        console.log(data);
        console.log(openGraphData);
        copyToClipboard.classList.remove("invisible");
      });
    });

    copyToClipboard.addEventListener("click", () => {
      navigator.clipboard.writeText(result.innerText);
      copyToClipboard.innerText = "Copied";
      setTimeout(() => {
        copyToClipboard.innerText = "Copy";
      }, 2000);
    });
  };

Solution

  • That's happening because useState hook is asynchronous, so if you log to the console the value of a state right after updating it, you'll see its previous value and not the updated one.

    One thing you can do is use the useEffect hook to log the state every time its value changes:

    useEffect(() => {
        console.log(openGraphData)
    }, [openGraphData])
    

    By putting your state inside the dependencies array, the function inside this useEffect will execute every time it updates.