Fetch using cached data when no internet connection - Javascript - React - javascript

I have a webapp that needs to use cached data when there's no internet connection. I have it working well now using a second fetch call inside the catch block but I feel this isn't the right approach.
fetch(api)
.then(resp => resp.json())
.then(json => {
this.setState({
result: json.Results,
})
})
.catch(e => {
const options = {
cache: "force-cache"
}
fetch(api, options)
.then(resp => resp.json())
.then(json => {
console.log(`failed to fetch --- using cached data`)
this.setState({
result: json.Results,
})
})
.catch(e => {
console.error("Insufficient data")
})
})
Is there a better way to go about this?

Checking for navigator.onLine was an easy conditional to avoid any issues.
https://davidwalsh.name/detecting-online

Related

Setting API data as state in React is undefined, but the API data exists

I have a weird issue with my React state. I'm fetching data from my NodeJS backend, and it comes back correctly in my frontend React app. But when I try to initialize a state with the data that was fetched, the state's value is "undefined", even though I know the data is coming back from the backend correctly.
here are the important parts of my react code:
const [currentCityData, setCurrentCityData] = useState({});
const fetchData = (cityValue) => {
axios.get('http://localhost:5000/get-weather', {
params: {
cityValue: cityValue
}
})
.then(res => console.log(res?.data?.data[0]))
.then((res) => setCurrentCityData(res?.data?.data[0]))
.then(console.log(currentCityData))
.catch(error => console.log(error))
};
useEffect(() => {
fetchData('toronto&country=canada');
}, []);
I'm getting the weather of a city. When I do a console log of the data I get back .then(res => console.log(res?.data?.data[0])) inside fetchData, the data is correct (its just an object with many weather properties). The line after that I set my state currentCityData, but then when I console log my currentCityData right after, its undefined.
Exactly what am I doing wrong here?
You are not returning aything from the first promise then handler. :
axios.get('http://localhost:5000/get-weather', {
params: {
cityValue: cityValue
}
})
.then(res => console.log(res?.data?.data[0])) // <--- here you should return
.then((res) => setCurrentCityData(res?.data?.data[0]))
.then(console.log(currentCityData))
.catch(error => console.log(error))
};
change your code to :
axios.get('http://localhost:5000/get-weather', {
params: {
cityValue: cityValue
}
})
.then(res => {console.log(res?.data?.data[0]); return res?.data?.data[0] }) // <--- here you should return
.then((res) => setCurrentCityData(res?.data?.data[0]))
.then(console.log(currentCityData))
.catch(error => console.log(error))
};
Demo : Demo

Pace-js not working with Axios inside Vue

I have the following axios call:
//Pace.restart();
Pace.start();
axios.post(`${this.url_base}/${this.system}`, consulta)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error.response.data);
})
.then(() => {
Pace.stop();
});
However Pace.start() simply won't fire and Pace.restart() will flash briefly instead of waiting for the stop signal from axios. What am I doing wrong?

How to Store Fetch API JSON Response in a JavaScript Object

I want to store a Fetch API JSON as a JavaScript object, so I can use it elsewhere. The console.log test works, but I can't access the data.
The Following Works: It shows console entries with three to-do items:
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => console.log(success));
The Following Does Not Work:
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => JSON.parse(success));
If I try to access success, it does not contain any data.
Have tried console.log, which works.
Have also tried the following, which works:
fetch('http://localhost:3000/api/todos')
.then(res => res.json())
.then(data => {
let output = '';
data.forEach(function (todo) {
output += `
<ul>
<li>ID: ${todo.id}</li>
<li>Title: ${todo.title}</li>
<li>IsDone: ${todo.isdone}</li>
</ul>
`;
});
document.getElementById('ToDoList').innerHTML = output;
return output;
})
.catch(err => console.log('Something went wrong: ', err));
However, I can't manually update inner HTML; I need the object to do other UX.
You can also use a function like below:
function doSomething(success){
//do whatever you like
}
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => doSomething(success));
You can just declare a variable outside and assign your result to it like this
var yourTodos;
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => yourTodos = success);
Then you have the yourTodos as your javascript object that you can use whatever you want.
You can use async await like below
async function consumingFunc () {
let response = await fetch('http://localhost:3000/api/todos')
console.log(response)
}
consumingFunc()

How control javascript error when json is empty

I am parsing a JSON file in javascript. Every 5 minutes the JSON is autoimatically updated with new data, during the time it is being updated the JSON is blank (for a about 2 seconds).
I get this error
Uncaught (in promise) SyntaxError: Unexpected end of JSON input
at fetch.then.res
This is the code in javascript for parsing the JSON:
fetch("http://location/file/data.json")
.then(res => res.json())
.then(data => {
//do something
})
How do I control this so that it doesn't flag this error? I still want an a customer error to appear using console.log(Error()).
Any help is appreciated.
This should do the trick. then() takes a second callback function as argument that receives the error object.
fetch("http://location/file/data.json")
.then(res => res.json(), err => console.log(err))
.then(data => {
//do something
}, err => console.log(err))
EDIT: As per comment, this way is preferred. Can read more about using promises in this link
fetch("http://location/file/data.json")
.then(res => res.json())
.then(data => {
//do something
})
.catch(err => console.log(err)
You can add .catch into your processing:
fetch("http://location/file/data.json")
.then(res => res.json())
.then(data => {
// do something
})
.catch(err => console.log(err.message))
EDIT: err.message instead of JSON.stringify(err).

Need guidance! Trying to learn about fetch() and Promises

Basically I'm trying to fetch the URL and URLPaths for two images I've uploaded (to Firebase) using the firebase function /storeImage and JSON.Stringify().
Below is the snippet of code that enables me to fetch data for the ONE image.
.then(token => {
authToken = token;
return fetch("myappURL/storeImage",
{
method: "POST",
body: JSON.stringify({
image: image.base64
}),
headers: {
Authorization: "Bearer " + authToken,
}
});
})
.catch(err => {
console.log(err);
alert("Oops! Something went wrong, please try again1")
dispatch(uiStopLoading());
})
.then(res => {
if (res.ok) {
return res.json();
} else {
throw(new Error());
}
})
.then(parsedRes => {console.log(parsedRes);
Now I want to fetch data from a second image.
What I gather, from the docs I've read, is that I should use promises for multiple async calls like what I have above. So, shouldn't something like this (see below) work?
.then(token => {
authToken = token;
let image = fetch(... image: image.base64 ...);
let coverImage = fetch(... coverImage: coverImage.base64 ...);
Promise.all([image, coverImage])
.then(ress => { ress.forEach(
res => {
process( res.json() );
})
})
.catch(err => {...})
.then(res => {...})
.then(parsedRes => {console.log(parsedRes);)
Spoiler alert. I tried and it didn't. But I cannot understand why.
When you chain promises together, that is, start a new promise inside a then callback you need to return it.
Promise.all returns a single new promise that resolves when all of the promises passed to it resolve. In your code above you're neglecting to return it.
E.g. Try running this code which logs undefined
Promise.resolve()
.then(() => {
Promise.all([Promise.resolve(1), Promise.resolve(2)])
})
.then(result => console.log(result))
vs this code which logs [1, 2]
Promise.resolve()
.then(() => {
return Promise.all([Promise.resolve(1), Promise.resolve(2)])
})
.then(result => console.log(result))

Categories