Flutter Listview not updating list items on UI - database

I'm working on a flutter app and using ListView.builder widget to show my data. I'm fetching data from database and showing it in listview. After i modify single listitem i want to refresh whole listview widget.
Currently the problem is that data which i am passing to listview widget is updating accordingly but not updating on UI.
Here is the screenshot of method in which i am fetching data from database and updating listview
Please help me. Thanks

You should use a streamBuilder for fetching the data and your method for fetching the data should be as follows :
Stream<List<Map<String,dynamic>>> fetchTimeLine() async* {
while(true) {
//first mention how much time to wait before fetching again I am using 10
// secs
await Future.delayed(Duration(seconds: 10));
try {
List<Map<String,dynamic>> allRows = await dbHelper.queryAllRows();
yield allRows ;
}
finally {
print('closed');
}
}
}

Related

Updating realtime database with react

I have a page of objects. These objects are retrieved from a json file in a firebase realtime database. On the page, I have put a checkbox input with each object.
Here's what I need: when the user checks off an object, the real time database is updated with a key value such as changed: true.
I've tried using the update function imported from firebase but doesn't seem to work.
Here is my handle function that controls the way my objects look when the corresponding checkbox is selected...
const handleCheckboxChange = (object) => {
if (selectedObjects.includes(object)) {
setSelectedObject(selectedObject.filter(b => b !== object));
} else {
setSelectedObject([...selectedObject, object]);
}
`
This works in changing the page, but how exaclty do I go about adding code to update to realtime database that the objects are selected?

How to access collections in Firebase Firestore

Ok my question is pretty basic, in my app I have a post system, and in that post you can like the post. So when the user clicks the like button, I want the database to update the likes. Only problem is... I don't know how to capture the collections data
This is what the data looks like, its a randomly generated collections id, I tried to set the collections id to the id of the user but that would mean I can't make multiple posts. Can anyone help on this?
You can store previous value of likes inside a variable using the get function present in Firestore. Then you can update a field in the Firestore document inside a collection using updateDoc method using the value as shown below
import {
getFirestore,doc,getDoc,updateDoc
} from 'firebase/firestore';
async function updateData() {
const docRef=doc(db,’collection’,’document’);
const docData=await getDoc(docRef);
var value=docData.get('likes');
updateDoc(docRef,{likes:value+1});
}
updateData();
Or you can use the increment function present in Firestore. It will increment your field directly and you won’t have to create a variable separately to store the previous value as shown in Add data
import {
getFirestore,doc,getDoc,updateDoc, increment
} from 'firebase/firestore';
async function updateData() {
const docRef=doc(db,’collection’,’document’);
await updateDoc(docRef,{likes:increment(1)});
}
updateData();
You can learn more about the update() in Update a document.

Fetch document only once when Firestore has updated

I have a tableView that bring all documents from Firestore collection and i want to fetch the last document only once when it is added to the Firestore after user refresh the tableView and after that I want to remove the listener so when the user refresh the tableView it only fetch document once , i used detach listener [from the documentation here][1] but it didn't work
func updatedFireStoredata() {
let listener = Firestore.firestore().collection("collection1").order(by: "date").limit(toLast: 1).addSnapshotListener() { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) {
let data = diff.document.data()
self.amount.append(data["amount"] as? String ?? "")
print("New city: \(diff.document.data())")
}
}
}
table2.reloadData()
listener.remove()
}
If your goal is to only call once to retrieve this document, I would consider using the offline persistence that is built in to the SDK. You will need to request the document once with offline persistence enabled, but after that call you can request this data from that local cache.
https://firebase.google.com/docs/firestore/manage-data/enable-offline
https://firebase.google.com/docs/firestore/manage-data/enable-offline#disable_and_enable_network_access
Alternatively you could store the document locally, and not include it in reload.
If it is the case that this data does change, just not as often as every refresh, it may make sense to move this to an eventing model. You can use firestore watch/listen to monitor that query and get update callbacks as needed. https://firebase.google.com/docs/firestore/query-data/listen
There are a couple of things
First, requiring a user to keep clicking refresh to get the current data is not a good experience. The data should be presented to the user automatically without interaction
Second, Firebase is asynchronous - code outside the Firebase closure will execute before the data in the closure. See my answer Firebase is asynchronous <- that's for the Realtime Database but the concept applies to asynchronous functions in general.
To fix both issues here's updated code
func updatedFireStoredata() {
let listener = Firestore.firestore().collection("collection1").order(by: "date").limit(toLast: 1).addSnapshotListener() { querySnapshot, error in
if let err = error {
print("Error fetching snapshots: \(err.localizedDescription)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) {
let data = diff.document.data()
self.amount.append(data["amount"] as? String ?? "")
print("New city: \(diff.document.data())")
}
}
table2.reloadData() //needs to be inside the closure
}
}
I moved the tableView reload inside the closure so it executes when new data arrives and then removed the code to remove the listener so your tableView will update with new data.
I also updated the error handler to handle an actual error code.
One thing you will want to do is to keep track of what the user has selected is is looking at - you don't want a selected item, for example, to un-select if other data is added which is what will happen when the tableView reloads.

How to Update an array without downloading all data from firebase ReactJs

Actually am new in react and am trying to create an event app in which a user can join an event
here is code for joining an event
export const JoinEvent = (id) => {
return async dispatch => {
let data = await firebase.firestore().collection('Events').doc(id).get()
let tmpArray = data.data()
let currentUser = firebase.auth().currentUser
let newArray = tmpArray.PeopleAttending
await firebase.firestore().collection('Events').doc(id).update({
PeopleAttending : {...newArray, [currentUser.uid]: {displayName : currentUser.displayName}}
})
}
}
actually i have created an action bascailly in JoinEvent an id is passed of the particular event which is clicked.
here is my firestore structure look like this..
so basically i have to download the whole data and store in local array and then add new user and then finally update
So here am basically download the whole data is there any way to just simply add new Object without downloading whole data??
thankyou
You are doing it wrong. Firestore document size limit is Maximum size for a document 1 MiB (1,048,576 bytes), so sooner or later you're going to reach that limit if you keep adding data like this. It may seems that you're not going to reach that limit, but it's very unsafe to store data that way. You can check Firestore query using an object element as parameter how to query objects in firestore documents, but I suggest you don't do it that way.
The proper way to do it, is to create a subcollection PeopleAttending on each document inside the Events collection and then use that collection to store the data.
Also you can try document set with merge or mergeFields like documented here https://googleapis.dev/nodejs/firestore/latest/DocumentReference.html#set and here https://stackoverflow.com/a/46600599/1889685.

Spring webflux data in ReactJs UI

I am playing around with spring webflux. I have created a project which would listen on a mongo capped collection and return the flux of data as and when it comes.
I am using #Tailablein my repository method.
My controller looks like this
#GetMapping("/findall")
public Flux<Product>> findAll() {
return productRepository.findAllProducts().;
}
This is working perfectly fine. I tested this by addind a doOnNext(...), Whenever there is a new item added to my capped collection, consumer inside the doOnNext is executed.
Now I want this to be displayed on the browser. And I wanted to do with ReactJs(I am completely new to frontend).
So far, I couldn't find any way to display the flux data in browser. What are the options by which I can achieve this.
I tried SSE(Server Sent Event) like this
componentDidMount() {
this.eventSource = new EventSource('http://localhost:8080/findall');
this.eventSource.addEventListener('product', (data) => {
let json = JSON.parse(data.data)
this.state.products.push(json.name)
this.setState ( {
products : this.state.products
})
});
}
This works perfectly fine, but for this to work, I had to change my server side code like this
#GetMapping("/findall")
public Flux<ServerSentEvent<Product>> findAll() {
return productRepository.findAllProducts().map(data -> ServerSentEvent.<Product>builder().event("product").data(data).build());
}
This, in my opinion is a bit tightly coupled because, UI should know the event type('product') to listen to.
Is there any other way to handle stream of events from UI side(particularly with reactjs) ?
You shouldn't have to change your controller in order to stream data to the browser. The following code snippet should work:
#GetMapping(path="/findall", produces=MediaType.TEXT_EVENT_STREAM_VALUE)
#ResponseBody
public Flux<Product>> findAll() {
return productRepository.findAllProducts();
}
You can see this feature being used in this workshop and this sample app if you'd like to see a complete working examples.

Resources