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;