Home > Back-end >  React simple useEffect infinit loop
React simple useEffect infinit loop

Time:02-22

I do not understand why this code is an infinit loop. I this it is because I update my state in else if condition. But i'd like to update an array of urls when getting new api answer.

import React, { useState, useEffect } from 'react';

function getShortenUrl() {
  const [urls, setUrls] = useState([])
  const [error, setError] = useState(null);
  const [items, setItems] = useState({});

  useEffect(() => {
    fetch("https://api.shrtco.de/v2/shorten?url=https://stackoverflow.com/questions/37435334/correct-way-to-push-into-state-array")
      .then(res => res.json())
      .then(
        (result) => {
          setItems(result);
        },
        (error) => {
          setError(error);
        }
      )
  }, [])

  if (error) {
    return <div>Error : {error.message}</div>;
  } else if (!items.result) {
    return <div>Loading...</div>;
    console.log("no item");
  } else {
    setUrls([urls, items]);
    console.log("items", items);
    console.log("urls", urls);
    return <ul> {items.result.short_link}</ul>;
  }
}


export default getShortenUrl;

I am kindof lost when it comes to state actually. I do not understand how I can create an array of urls and be able to use it in other components.

CodePudding user response:

You may have some mistakes here

      .then(
        (result) => {
          setItems(result);
        },
        (error) => {
          setError(error);
        }
      )

Change it into

.then((result) => {
          setItems(result);
          setUrls([...urls, result])
})
.catch((error) => {
          setError(error);
})

And also remove the line setUrls([urls, items]);

CodePudding user response:

If you are new to react then we make Loading state for API Call fetch and you are setting state in else and when state updates component re-renders so on every component re-render you are updating state which is causing infinite loop. Try this

import React, { useState, useEffect } from 'react';

function getShortenUrl() {
  const [urls, setUrls] = useState([])
  const [error, setError] = useState(null);
  // const [items, setItems] = useState({}); // remove it because you are using urls and items state for same purposes
  const [loading,setLoading]=useState(false);

  useEffect(() => {
    setLoading(true);
    fetch("https://api.shrtco.de/v2/shorten?url=https://stackoverflow.com/questions/37435334/correct-way-to-push-into-state-array")
      .then(res => res.json())
      .then(
    (result) => {
      // setItems(result); // remove it
      setUrls(result);
      setLoading(false);
    },
    (error) => {
      setError(error);
      setLoading(false);
    }
      )
  }, [])
      if(loading){
           return <div>Loading...</div>;
      }
  if (error) {
    return <div>Error : {error.message}</div>;
  } else {
    return <ul> {urls?.result?.short_link}</ul>;
  }
}


export default getShortenUrl;

CodePudding user response:

Try to use a conditional rendering instead of if else statement:

import React, { useState, useEffect } from 'react';

function getShortenUrl() {
  const [urls, setUrls] = useState([])
  const [error, setError] = useState(null);
  const [items, setItems] = useState({});

  useEffect(() => {
    fetch("https://api.shrtco.de/v2/shorten?url=https://stackoverflow.com/questions/37435334/correct-way-to-push-into-state-array")
      .then(res => res.json())
      .then(
        (result) => {
          setItems(result);
        },
        (error) => {
          setError(error);
        }
      )
  }, [])

return (

         <>
             {error&& <div>Error : {error.message}</div>}
             {!items.result && <div>Loading...</div> }
             {items.result &&  <ul> {items.result.short_link}</ul>}
        </>
   )
 
}


export default getShortenUrl;

  • Related