I'm trying to make a workable App where you get from an API some data and that data is randomly changes every 3 seconds and with a button the user can print the data and by pressing again it stops, i have managed to complete this(as seen bellow) part(btw new to react js):
useEffect(() =>{
const interval = setInterval(() => {
getJoke()
},3000);
return () => clearInterval(interval);
},[])
//fetch the jokes function
const getJoke = (() => {
fetch('https://api.chucknorris.io/jokes/random')
.then((res) => res.json())
.then((res) => {
setKey(res.id);
setJoke(res.value);
})
.catch((err) => console.log(err));
})
i have also made a button where the user can save the data(which randomly appears every 3 sec) on the localStorage of the browser as seen bellow..
const addJokeFav = (() => {
jokes.push(joke);
const jokesJsonified = JSON.stringify(jokes);
localStorage.setItem(key, jokesJsonified);
})
bellow the render code
<button id="button" onClick={()=>{addJokeFav()}}>Save!</button>
but i would like to have only one button where he save one data coming randomly and every 3 seconds, and if he repress the button the data will be deleted from the localStorage. i have this function here which i dont seem to make it work.
const remJokeFav = (() => {
const jokesJsonified = JSON.stringify(jokes);
localStorage.removeItem(key, jokesJsonified);
})
it seems that is trying to remove and item that is not there cause of the key, which i take it with setKey(res.id) on the response, on the code above in the first snippet.
my App variables are bellow.
const [joke, setJoke] = useState();
const [key, setKey] = useState([]);
const [isActive, setActive] = useState("false");
const jokes = [];
Thanks for any help regarding the situation!
The problem looks to be with localStorage.removeItem(key, jokesJsonified);
removeItem just needs the key and not the value.
Also there is unnecessary rerender on setting jokes array. Make jokes array as ref instead of state.
Here is an working example in codesandbox
Related
Here is the new script with the find function which allows me to identify a single element of the array for sure but there is still a small problem. As you can see it's my const crypto which contains the data I want to display on the front end. However when I want to call crypto at the return level the const is not recognized.
Hello again,
I updated the script now it works I can display on the front end the data I want however I have the impression that the request to the api is executed several times when I would like there to be only one request
I put below a screen of the console.log of my script.
As you can see the data requested is displayed first as undefined then it is displayed several times, then I put blocked due to the too large number of requests made in little time
Thanks for your help
How do I make my requests :
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://localhost:4500/coingeckotest")
.then(response => {
if (response.ok) {
return response.json()
}
throw response;
})
.then(data => {
setData(data)
})
.catch(error => {
console.error("Error fetching data: ", error)
setError(error)
})
.finally(() => {
setLoading(false)
})
}, [])
const uniswap = data&&data[0].tickers?.find(donne =>
donne.trade_url === 'https://app.uniswap.org/#/swap?
inputCurrency=0x2260fac5e5542a773aa44fbcfedf7c193bc2c599&
outputCurrency=ETH')
const uniprice = uniswap?.converted_last?.usd
const sushiswap = data&&data[1].tickers?.find(donne =>
donne.trade_url === 'https://app.sushi.com/swap?
inputCurrency=0x2260fac5e5542a773aa44fbcfedf7c193bc2c59
9&outputCurrency=ETH')
const sushiprice = sushiswap?.converted_last?.usd
const curvefinance = data&&data[2].tickers?.find(donne =>
donne.base === 'DAI')
const curveprice = curvefinance?.converted_last?.usd
const quickswap = data&&data[3].tickers?.find(donne =>
donne.trade_url === 'https://quickswap.exchange/#/swap?
inputCurrency=0x0d500b1d8e8ef31e21c99d1db9a6444d3adf127
0&outputCurrency=0xbbba073c31bf03b8acf7c28ef0738decf369
5683')
const quickprice = quickswap?.converted_last?.usd
console.log(uniprice)
console.log(sushiprice)
console.log(curveprice)
console.log(quickprice)
if (loading) return "Loading..."
if(error) return "Error !"
return (
<>
</>
)
}
export default App;
Thank you in advance for your answers
You can use the Array.find method to find out the first entry that matches a particular coin_id. The code for that would be:
const desiredCoinID = "something"; (determined by some user input)
const desiredCoinObject = data.find(coin => coin.coin_id === desiredCoinID);
const priceInUSD = desiredCoinObject?.tickers?.converted_last?.usd;
——-Updated Answer——-
Hi, this is my answer to your updated question. const crypto that you use is available only within the scope of the callback of the useEffect function, which is why you cannot see the results on your screen. There are two ways you can go about it:
First, you can declare crypto as a let outside the useEffect and then update it inside your useEffect. That way your crypto will have global scope. But there is a better way to do this, which is to use the useState hook.
You can declare a crypto, setCrypto using useState and then use the setter to update the value if crypto inside useEffect after the data fetching is over. Let me know if you need help writing code.
New to coding last month and I'm learning JS through React Native.
I've added a Firestore DB to pull data through to my app and put together a call-back function using the useState hook due to it being Async.
My issue is my DBSearch function is now looping infinitely.
Code below:
const [propertyData, setPropertyData] = React.useState(["Well, this is awkward..."])
const colRef = (listName) => collection(db, listName)
const dbSearch = (listName, callBackFuncHere) => {onSnapshot(colRef(listName), (snapshot) => {
let newList = []
snapshot.docs.forEach(doc => {
newList.push({ ...doc.data(), id: doc.id }) // Pulls Object Data and runs for loop to assign to newList Array
})
callBackFuncHere(newList)
})};
function retFunc(newList){
setPropertyData(newList)
console.log('1')
}
dbSearch('propertyList', retFunc)
Is this an improper use for useState? and how should I change my dbSearch function to stop it continually looping?
Apologies if this has been asked a thousand times before, I'm unsure how to clearly articulate and search for my problem.
So suppose I have a page that displays all the user's posts. Right now when the user creates a post, it stores it into the database. But that new post will not appear unless I log out of the app and log back in. How can I make it so that the post will appear without having to logout?
const [Posts,setPosts] = useState([])
useEffect(()=>{
const fetchUserPosts = async () => {
const res = await client.get('/fetch-user-posts')
setPosts(res.data.posts)
}
fetchUserPosts()
},[])
And in the rendering I just took the Posts and map it to display its contents. I know this problem exists somewhere but I don't know what keywords to google. I have seen posts asking to use JQuery but I bet there is a simpler solution? Any pointers are appreciated.
Take the function of fetchUserPosts out of the useEffect like this:
const fetchUserPosts = async () => {
const res = await client.get('/fetch-user-posts')
setPosts(res.data.posts)
}
Now, useEffect will be like this:
useEffect(() => {
fetchUserPosts()
}, [])
Next, wherever you function of create user posts is, call fetchUserPosts() like this:
const addUserPosts = async () => {
// logic of adding new user post
if (success) {
await fetchUserPosts()
}
}
Here's my page:
function MyAssets() {
const [assetData, setAssetData] = useState({})
const [assetArray, setAssetArray] = useState([{symbol:'', amount:''}])
and its component below.
I'm trying to fetch data in this component, I set a setInterval to run it every second.
but requests are too many, it sometimes send back status code 429 and fail.
So I add an if statement, if I fetched data successfully, I clear this setInterval .
This one failed too, it seems every time it triggers setState, the whole component render again, and my checkState become false, and triggers again.
How should I stop this component once I fetch date from API successfully?
//React component
function AssetRow(props) {
const [price, setPrice] = useState(null)
const [checkState, setCheckState] = useState(false)
const fetchStockPrice = async()=>{
const data = await api.getStock(props.item.symbol)
setPrice(data.data.latestPrice)
}
//I try to run fetchStockPrice() every 1 second here
useEffect(()=>{
const doWork = setInterval(() => {
if (checkState === false){
fetchStockPrice()
setCheckState(true)
} else if (checkState === true) {
clearInterval(doWork)
}
}, 1000)
return () => clearInterval(doWork)
}, [])
return (
<h1>{price}</h1>
)
}
I have a react component with this state
const [name, setName] = useState('')
const [comment, setComment] = useState('')
const [notes, setNotes] = useState([])
this function handles the input elements to fill the order
const handleComments = () => {
setNotes([...notes, {
name,
comment
}])
setName('')
setComment('')
}
and this function sends the info to the server
const update = async () => {
const newNotes = notes.map(note => ({
name,
comment
}))
return updateNotesPromise(newNotes)
}
here I have a button that has to execute both functions
<Button onClick={} />
How can I create a function that is passed through the onClick method and executes handleComments in order to load the info on the DOM and then, once that info there, executes the update function and saves the order info into the DB ?
It looks like you're using functional components, so you can create a useEffect that makes an API put request whenever notes gets updated:
useEffect(()=> {
updateNotesPromise(notes);
},[notes])
I'm assuming updateNotesPromise is a function that makes your request call? It's also unclear why newNotes is being mapped from notes, or why update is async when it doesn't await anything. Your onClick would simply trigger handleNotes (I'm assuming that is your submit button).
Here's a way to handle the component updating and server communicating with error handling:
const onButtonClicked = useCallback(async (name, comment) => {
// cache the olds notes
const oldNotes = [...notes];
// the updated notes
const newNotes = [...notes, {
name,
comment
}];
// update the component and assume the DB save is successful
setNotes(newNotes);
try {
// update the data to DB
await updateNotesPromise(newNotes);
} catch(ex) {
// when something went wrong, roll back the notes to the previous state
setNotes(oldNotes);
}
}, [notes]);