data showing but not showing in useState hook - javascript

const response = product.map((item) => {
return item.images;
});
console.log("response is ", response);
const [productItem, setProductItem] = useState(response);
console.log("usestate is ", productItem);
please help me as soon as possible I am stuck here for like 3 days and don't know what to do
I have tried alot to solve this issue and it is working in console before usestate initialization but once I add usestate hook it will not show up

Initially declare the state as null / empty array
const [productItem, setProductItem] = useState(null)
Then use useEffect to set the response to state.
useEffect(() => {
const product = [........]
const response = product.map((item) => {
return item.images;
});
setProductItem(response)
},[])

Related

How to identify an element in a table whatever its place

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.

React SWR - how to know that updating (mutating) is running?

Im mostly using SWR to get data, however I have a situation that I need to update data. The problem is, I need an indicator that this request is ongoing, something like isLoading flag. In the docs there's a suggestion to use
const isLoading = !data && !error;
But of course when updating (mutating) the data still exists so this flag is always false. The same with isValidating flag:
const { isValidating } = useSWR(...);
This flag does NOT change when mutation is ongoing but only when its done and GET request has started.
Question
Is there a way to know if my PUT is loading? Note: I dont want to use any fields in state because it won't be shared just like SWR data is. Maybe Im doing something wrong with my SWR code?
const fetcher = (url, payload) => axios.post(url, payload).then((res) => res);
// ^^^^^ its POST but it only fetches data
const updater = (url, payload) => axios.put(url, payload).then((res) => res);
// ^^^^^ this one UPDATES the data
const useHook = () => {
const { data, error, mutate, isValidating } = useSWR([getURL, payload], fetcher);
const { mutate: update } = useSWRConfig();
const updateData = () => {
update(getURL, updater(putURL, payload)); // update data
mutate(); // refetch data after update
};
return {
data,
updateData,
isValidating, // true only when fetching data
isLoading: !data && !error, // true only when fetching data
}
Edit: for any other who reading this and facing the same issue... didnt find any solution for it so switched to react-query. Bye SWR
const { mutate: update } = useSWRConfig();
const updateData = () => {
// this will return promise
update(getURL, updater(putURL, payload)); // update data
mutate(); // refetch data after update
};
By using react-toastify npm module to show the user status.
// first wrap your app with: import { ToastContainer } from "react-toastify";
import { toast } from "react-toastify";
const promise=update(getURL, updater(putURL, payload))
await toast.promise(promise, {
pending: "Mutating data",
success: "muttation is successfull",
error: "Mutation failed",
});
const markSourceMiddleware = (useSWRNext) => (key, fetcher, config) => {
const nextFetcher = (...params) =>
fetcher(...params).then((response) => ({
source: "query",
response,
}));
const swr = useSWRNext(key, nextFetcher, config);
return swr;
};
const useHook = () => {
const {
data: { source, response },
mutate,
} = useSWR(key, fetcher, { use: [markSourceMiddleware] });
const update = mutate(
updateRequest().then((res) => ({
source: "update",
response,
})),
{
optimisticData: {
source: "update",
response,
},
}
);
return {
update,
updating: source === "update",
};
};
Hmm based on that:
https://swr.vercel.app/docs/conditional-fetching
It should work that the "is loading" state is when your updater is evaluates to "falsy" value.
REMAINDER! I don't know react swr just looked into docs - to much time at the end of the weekend :D
At least I hope I'll start discussion :D

React JS: remove an item from the localStorage

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

Make an http request and parse the data in React

I am trying to make an http request to my backend server (run on java springboot) with my React-based frontnend, which returns a string that I want to parse and assign to values. From what I have seen on the syntax pages, I want to believe that I am calling the request correctly. My error message mentions "Cannot read properties of undefined (reading 'split')", which I think means that split() is not a valid operation for js or React? Does anyone know what is the correct way to this?
import React from 'react';
import './App.css';
import Exchange from './Exchange'
import Recommendations from './Recommendations';
import axios from "axios";
function Middle(){
const response = axios.get("http://localhost:8080/run");
const data = response.data;
const dataArr = data.split(",");
return (
<div className = 'Middle'>
<h1>{data}</h1>
<Exchange name = "Coinbase" btcBuy = {dataArr[1]} btcSell = "" ethBuy = "" ethSell = ""/>
<Exchange name = "Binance" btcBuy = "" btcSell = "" ethBuy = "" ethSell = ""/>
<Recommendations/>
</div>
);
};
export default Middle;
It means that the data variable is not a string. Also you need to use useEffect if you want to fetch data.
import React, { useState, useEffect } from "react";
function Middle(){
const [data, setData] = useState([]);
useEffect(() => {
(async () => {
try {
const response = await axios.get("http://localhost:8080/run");
const data = response.data;
setData(data); // use split if you have to, I dont think you need that.
} catch(err) {
console.error(err);
}
})()
}, [])
Actually you do not read the response properly, as it is an asynchronous operation and your response is undefined at the time you make operations on it sequentially.
You have to place your code in the body of .then, like this:
let dataArr = [];
axios.get("http://localhost:8080/run")
.then(response => {
const data = response.data;
dataArr = data.split(",");
});

Infinite Loop when setting setState hook as class attribute in Effect hook

I have an Effect hook in a React component that sets up and initialises a class that I use to communicate with a backend server:
const SignalProvider = ({url, children}) => {
let [sigErr, setSigErr] = useState("")
let [token, setToken] = useContext(TokenContext)
let [signaller, setSignaller] = useState()
useEffect(() => {
if (!signaller) {
const s = new Signaller(url, (err) => setSigErr(err))
setSignaller(s)
}
if (token && signaller) {
signaller.setToken(token)
signaller.setSetTokenCallback(setToken) // Adding this line causes an infinite loop
signaller.connect()
}
}, [url, token, signaller, setToken, authError])
...
}
However, adding the line signaller.setSetTokenCallback(setToken) causes an infinite loop of re-rendering. Without this line it works as expected.
All setSetTokenCallback does is:
setTokenCallback(f) {
this.setTokenCallback = f
}
Which I don't think should matter.
Whats the best way to prevent the loop?
Have you tried using 'useCallback()' hook?
const initializeClass = useCallback(() => {
if (!signaller) {
const s = new Signaller(url, (err) => setSigErr(err))
setSignaller(s)
}
if (token && signaller) {
signaller.setToken(token)
signaller.setSetTokenCallback(setToken)
signaller.connect()
}, [url, token, signaller, setToken, authError])
useEffect(() => {
initializeClass()
}, [bla bla all dependencies needed])
I think your culprit is in these lines
signaller.setToken(token) // first possible culprit
signaller.setSetTokenCallback(setToken)
Since you are setting the token inside the useEffect and your useEffect depends on the token value for a re-evaluation again. If the token value is different than the previous one then it will make the useEffect to re-render.
[url, token, signaller, setToken, authError] // second possible culprit
Also, you should remove object or array type variables from the condition array [url, token, signaller, setToken, authError] or stringify them or find some way to compare, as objects and arrays can't be compared directly. They will always return false if directly compared. Thus, your useEffect will re-run.

Categories