React Native iOS is saving fetched data until I uninstall the app? - ios

I am trying to figure out what is causing this issue. When I open the app, I go to the first screen. The screen contains data that is fetching from json data. Then when I switch to another screen and back to the first screen the same data is still there. I'll explain why it should be different. I am fetching data from mysql database using a random query (RAND()) It should be different every time I go back to the first screen.
When I uninstall and reinstall the app, I see the newly fetched data, but the problem still proceeds if I repeat the steps.
This works on Android, but not on iOS:
componentDidUpdate(prevProps, prevState) {
if (!prevState.user_image) {
fetch('https://www.exmaple.com/React/user.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
user_image: responseJson
}, function() {
const {userLikes, user_image} = this.state;
this.setState({
combinedArray: userLikes.map(likes => Object.assign(likes, user_image.find(images => images.id == likes.id)))
});
});
})
.catch((error) => {
//console.error(error);
});
}
}
I don't know if Xcode have some kind of fetch data caching. Basically what is happening is (In web development terms) CSS caching, but with fetched data. If that makes sense.
Also I am using a react-native-react-navigation Tab Navigation...maybe that's the problem and it's saving fetched data?

It turns out I was right! It was because the fetch is caching. I had to insert no caching headers in the fetch.

Related

Ionic 4 - Platform.resume event calling

I have an Ionic 4 app in which we have three tabs. Each tab contains data which will be retrieved from api call. The data will change frequently.
When we move between tabs the api will be called and the data will be re-binded. We had a requirement that when the app is minimized and open again the api has to be called and the data has to be re-binded.
I used the platform resume event as below in all the three tabs.
this.platform.ready().then(() => {
this.platform.resume.subscribe((e) => {
// API call of each function (different api for tabs)
});
});
Now, When the app is resumed after minimized, the platform resume event is called by it is calling multiple times as I used resume event in all the three tabs.
Please help to overcome this problem. Thanks in advance.
I'm not sure but what I gather from your question and comments, it would make sense to have a subject that will update on resume and on each tab have the function that request each API listening to that observable?
something like this: (on main app)
this.platform.ready().then(() => {
this.platform.resume.subscribe((e) => {
this.appResumedSubject.next(true);
});
});
and on tab1:
this.appResumedObservable.subscribe(result => {
if(result){
this.apiCall1();
}
});
and on tab2:
this.appResumedObservable.subscribe(result => {
if(result){
this.apiCall2();
}
});
to make it work seamlessly on both tabs it would be needed to have appResumeSubject defined on a service provider.

How can I persist newly saved values across components? Pulling original values from DOM

I have 3 different components with buttons to navigate across them. All of the default form values are pulled from the DOM and set into the data beforeMount. The reason I'm doing it this way is that the values are coming from my Rails database.
When I edit a form and save it successfully (via ajax), everything is good but once I switch components using the navigation, those values in the inputs are reset back to the original/old values since the beforeMount is running again and the DOM was not updated with the new value (due to no refresh yet).
I tried changing the original values in the DOM with jQuery upon every update but that didn't work. It would work once but further updates didn't change.
Here is how I'm setting the data inside of the beforeMount:
const element = document.getElementById('setting');
const setting = JSON.parse(element.dataset.setting)
this.discountType = setting.discount_type;
Then, upon every ajax request I tried to edit those original values in the DOM which didn't work:
outerThis = this;
Rails.ajax({
url: '/update-settings',
type: 'POST',
data: data,
dataType: 'json',
success: (data) => {
ShopifyApp.flashNotice('Successfully updated')
var settings = $('#setting').data('setting')
settings.discount_type = outerThis.discountType
},
error: (err) => {
ShopifyApp.flashError('There was an error')
}
})
What's the recommended way to go about this issue?

React native PouchDB get hangs

I have a promise chain where I get the content from local DB, update it with the latest fetched from API. This cycle is run whenever user eg opens a content. It works well. Except when the user is opening the app through a deep link. Eg, I go to the company website, I have the deep link option in the safari, I open it. It successfully fetches the content opened from the website, goes into the promise lifecycle where it tries to load and update the content but it just hangs. All input data is correct and it doesn't make sense why it hangs at all.
PouchDB is using adapter pouchdb-adapter-react-native-sqlite with react-native-sqlite-2
createDBIndex()
.then(() => {
console.groupCollapsed('Updating existing content');
console.log(toUpdateArray);
console.log('Fetching articles and indexes');
return Promise.all(toUpdateArray.map(({ _id }) => DB.articles.get(_id)));
})
.then(dbArticles => {
console.log('Resolving finders-keepers');
console.log(dbArticles);
const updatedContent = dbArticles.map(dbItem => {
const toUpdate = toUpdateArray.find(item => item._id === dbItem._id);
return {
...dbItem,
...toUpdate,
expire: moment().add(1, 'd').format()
};
});
return DB.articles.bulkDocs(updatedContent).then(() => updatedContent);
})
.then(updatedDBArray => {
console.log('update result', updatedDBArray);
console.groupEnd();
return updatedDBArray;
})
The last console.log it gives is Fetching articles and indexes and the whole app freeze. tried to print the PouchDB get function result or error but nothing. It doesn't get resolved or rejected.
What I can share is that recently people have problems using PouchDB in a React Native environment which is using AsynchStorage as its backing storage. Take a look at this question and that question and also this issue.

React Native Axios.get returned results not fresh

I'm using axios to fetch data for my React Native app and I'm having an issue only for iOS. I am able to fetch data from my server perfectly fine, however if I change any data from my API, the changes doesn't reflect in iOS at all, only when I re-install the app then the changes will take place. I'm still not able to pinpoint what is causing the issue. This is only happening in iOS, Android works perfectly fine.
Fetch Data code:
axios.get('http://www.example.com/api')
.then((response) => {
// console.log(response);
this.setState({ data: response.data, loading: false });
});
Please let me know if I miss out any information.
If this has already been asked, I would greatly appreciate if you are able to point me in the right direction.
Thank you so much!
my guess is that the page is read from the cache and so you get an old copy.
what you need to do is to add a date stamp to the link, in order to force the app to load a 'fresh' page.
it goes something like that:
axios.get('http://www.example.com/api?dt='+(new Date()).getTime())
.then((response) => {
// console.log(response);
this.setState({ data: response.data, loading: false });
});
It can be resolved by adding headers: {'Cache-Control': 'no-cache'} to the header.
axios.get('http://www.example.com/api',
headers: {'Cache-Control': 'no-cache'})
.then((response) => {
// console.log(response);
this.setState({ data: response.data, loading: false });
});

Service Worker and transparent cache updates

I am trying to install a ServiceWorker for a simple, yet old, Django web app. I started working with the example read-through caching example from the Chrome team
This works well but isn't ideal because I want to update the cache, if needed. There are two recommended ways to do this based on reading all the other service-worker answers here.
Use some server-side logic to know when the stuff you show has updated and then update your service worker to change what is precached. This is what sw-precache does, for example.
Just update the cache version in the service worker JS file (see comments in the JS file on the caching example above) whenever resources you depend on update.
Neither are great solutions for me. First, this is a dumb, legacy app. I don't have the application stack that sw-precache relies on. Second, someone else updates the data that will be shown (it is basically a list of things with a details page).
I wanted to try out the "use cache, but update the cache from network" that Jake Archibald suggested in his offline cookbook but I can't quite get it to work.
My original thinking was I should just be able to return the cached version in my service worker, but queue a function that would update the cache if the network is available. For example, something like this in the fetch event listener
// If there is an entry in cache, return it after queueing an update
console.log(' Found response in cache:', response);
setTimeout(function(request, cache){
fetch(request).then(function(response){
if (response.status < 400 && response.type == 'basic') {
console.log("putting a new response into cache");
cache.put(request, response);
}
})
},10, request.clone(), cache);
return response;
But this doesn't work. The page gets stuck loading.
whats wrong with the code above? Whats the right way to get to my target design?
It sounds like https://jakearchibald.com/2014/offline-cookbook/#stale-while-revalidate is very close to what you're looking for
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
// if we got a response from the cache, update the cache
if (response) {
cache.put(event.request, networkResponse.clone());
}
return networkResponse;
});
// respond from the cache, or the network
return response || fetchPromise;
});
})
);
});
On page reload you can refresh your service worker with new version meanwhile old one will take care of request.
Once everything is done and no page is using old service worker, It will using newer version of service worker.
this.addEventListener('fetch', function(event){
event.responseWith(
caches.match(event.request).then(function(response){
return response || fetch(event.request).then(function(resp){
return caches.open('v1').then(function(cache){
cache.put(event.request, resp.clone());
return resp;
})
}).catch(function() {
return caches.match('/sw/images/myLittleVader.jpg');
});
})
)
});
I recommend you to walk through below link for detailed functionality
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers

Resources