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.
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]);
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;
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
I followed a Reat.js teching video by a YouTube uploarder The Net Ninjia YouTube
In this video, the author indecated a runtime warning:Warning:Can't perform a React state update on an unmounted component.
But according to the following code I can't reproduce this waring.My code works just fine.
So what happened to this following code? Is it because React.js updated something?
import { useState, useEffect } from 'react';
const useFetch = (url) => {
const [data, setData] = useState(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// const abortCont = new AbortController();
setTimeout(() => {
fetch(url)
.then((res) => {
// console.log(res);
if (!res.ok) {
throw Error('could not fetch data for some reason');
} else {
return res.json();
}
})
.then((res) => {
setData(res);
setIsPending(false);
setError(null);
})
.catch((err) => {
console.log(err);
});
}, 2000);
}, [url]);
return { data, isPending, error };
};
export default useFetch;
However, I followed the video, changed the code as below, it raised a AbortError.But according to the author, this error won't happen.
import { useState, useEffect } from 'react';
const useFetch = (url) => {
const [data, setData] = useState(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const abortCont = new AbortController();
setTimeout(() => {
fetch(url, { signal: abortCont.signal })
.then((res) => {
if (!res.ok) {
throw Error('could not fetch data for some reason');
} else {
return res.json();
}
})
.then((res) => {
setData(res);
setIsPending(false);
setError(null);
})
.catch((err) => {
if (err.name === 'AbortError') {
console.log(err.name);
} else {
setIsPending(false);
setError(err.message);
}
});
}, 2000);
return () => abortCont.abort();
}, [url]);
return { data, isPending, error };
};
export default useFetch;
I am a beginner and I am learning React JS. I am doing a basic project in React. I have a search box. When I search for something my page will show search related content.
Here I used includes() to make my search workable. But it is not working.
I have indicated the line of setting a new array of dogs at line 40.
Pleae have a look to my code.
Here is my codes:
Home.jsx
import React, { useState, useEffect } from 'react';
import Dogs from './components/Dogs/Dogs';
import Search from './components/search/Search';
const Home = () => {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [value, setValue] = useState('');
const [search, setSearch] = useState('');
const [dogs, setDogs] = useState([]);
useEffect(() => {
fetch('https://api.thedogapi.com/v1/breeds', {
headers: {
Authorization: '4139956d-7014-4fa8-b295-8e361418c807',
},
})
.then(response => response.json())
.then(
data => {
setIsLoaded(true);
setDogs(data);
},
error => {
setIsLoaded(true);
setError(error);
}
);
}, []);
const handleChange = event => {
setValue(event.target.value);
};
const handleSearch = () => {
setSearch(value);
setValue('');
};
// This is the function to making a new array of dogs of searched name
useEffect(() => {
const newDogList = dogs.filter(dog => {
if (dog.name.includes(search)) dog
});
setDogs(newDogList);
}, [search]);
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="container">
<Search
value={value}
handleChange={handleChange}
handleSearch={handleSearch}
/>
<Dogs dogs={dogs} />
</div>
);
}
};
export default Home;
How can I make it workable?
I want to update the Category list after delete a category, I used custom hook for fetching data from the server. I'm not sure how to update state on custom fetch hook
const {data, error, loading} = useFetch("/api/admin/category");
const [category, setCategory]= useState([]);
useEffect(() => {
setCategory(data)
},[])
const deleteHandler = (id) => {
const deleteRequest = async () => {
const data = await axios.delete(`/api/admin/category/${id}`);
return data;
}
deleteRequest()
.then(res => {
data.filter((item) => {
return id !== item.id;
})
})
}
Adding data as the dependency to the useEffect hook may help, try this,
const {data, error, loading} = useFetch("/api/admin/category");
const [category, setCategory]= useState([]);
useEffect(() => {
setCategory(data)
},[data])
const deleteHandler = (id) => {
const deleteRequest = async () => {
const data = await axios.delete(`/api/admin/category/${id}`);
return data;
}
deleteRequest()
.then(res => {
data.filter((item) => {
return id !== item.id;
})
})
}
could you add you're custom hook to the code provided? and also be a bit more specific with your query?
import {useEffect, useState} from "react";
import axios from "axios";
const useFetch = (url) => {
const [data, setData,isLoading] = useState([]);
const [error, setError] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
request_get()
.then(res => {
if (res.request.status === 200) {
setTimeout(() => {
setLoading(false)
setData(res.data.data)
},1000)
}
})
return () => {
setData([]);
}
}, [])
const request_get = async () => {
const data = await axios.get(url)
return data;
}
return {data: data, error: error, loading:loading}
}
export default useFetch;
in your custom hook add data to your dependency array;
in your component instead of the folowing
useEffect(() => {
setCategory(data)
},[])
try to use the spread operator
useEffect(() => {
setCategory([...data])
},[data])
I am doing inference using flask rest API and I got the result
{
result: {
predictions: -3.4333341121673584
} }
bypassing multiple args in the get as the URL I got the above result
http://127.0.0.1:3000/predict?solute=CC(C)(C)Br&solvent=CC(C)(C)O Now I want to use this result to use in a react app.
I have written the code below
import { useState, useEffect } from "react";
function App() {
const [state, setState] = useState({});
useEffect(() => {
fetch("api/")
.then((response) => {
if (response.status == 200) {
return response.json();
}
})
.then((data) => console.log(data))
.then((error) => console.log(error));
});
I have written the following using a tutorial on the internet. I am new to using fetch API or Axios. Need help to get this result in react app
import { useState, useEffect } from "react";
function App() {
const [data, setData] = useState(null);
const [loading, setLoading = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch("http://127.0.0.1:3000/predict?solute=CC(C)(C)Br&solvent=CC(C)(C)O")
.then((response) => {
if (response.status == 200) {
return response.json();
}
})
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) {
return <p>Loading</p>
}
if (error) {
return <p>{JSON.stringify(error)}</p>
}
return <p>{JSON.stringify(data)}</p>
}
I want to render a list from a JSON URL. However, I have the following error: Objects are not valid as a React child (found: TypeError: Failed to fetch). If you meant to render a collection of children, use an array instead. What am I going wrong? Thanks for your answer
//hooks.tsx
import { useEffect, useState } from 'react'
export const useFetch = () => {
const [data, setData] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
useEffect(() => {
setLoading(true)
setError(null)
fetch('https://jsonkeeper.com/b/Z51B')
.then(res => res.json())
.then(json => {
setLoading(false)
if (json.data) {
setData(json.data)
} else {
setData([])
}
})
.catch(err => {
setError(err)
setLoading(false)
})
}, [])
return { data, loading, error }
}
//index.tsx
import React from 'react';
import { useFetch } from "./hooks.js";
import {CardItem} from './card';
export const List = () => {
const { data, loading, error } = useFetch()
if (loading) return <div>Loading...</div>
if (error) return <div>{error}</div>
return (
<>
<ul>
{data.map((item: any, index: any) => (
<li key={index}>
{item.names.map((name: any) => {
return <CardItem
family={item.family}
name={name}
/>
})
}
</li>
))}
</ul>
</>
);
};
I guess the problem is with your setError(err) in catch block of your custom hook. It should be setError(err.message).