0

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.

1
  • You shouldn't have individual return statements: instead, have one single return statement and use if/else logic inside the return statement instead for conditional rendering. Commented Feb 22, 2022 at 9:43

3 Answers 3

1

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]);

Sign up to request clarification or add additional context in comments.

2 Comments

Hey, thank you for your answer. How do I use the returned short_link to fill an array in an other component ?
With this case, you should create and use useContext vs dispatch. Check it out with this guide and example here: kentcdodds.com/blog/how-to-use-react-context-effectively
0

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;

2 Comments

Hey, thank you for your answer. How do I use the returned short_link to fill an array in an other component ?
You can store it globally either using Context or Redux to avoid props drilling. And you can also send to child component via props. like <Child array={urls?.result?.short_link}/>
0

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;

1 Comment

Hey, thank you for your answer. How do I use the returned short_link to fill an array in an other component ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.