Reputation: 16102
On the first load of the page after a user login event, I want to populate the items
property with a set of objects stored in my Firebase.
A achieves my desired behavior.
A<firebase-query
id="query"
...
path="users/[[user.uid]]/widgets"
data="{{items}}">
</firebase-query>
B does not.
B<firebase-query
id="query"
...
path="widgets"
data="{{items}}">
</firebase-query>
When using B, I expect to see the items
object populate, but instead the items
object is null. However, if I refresh the browser manually (without logging out) the element behaves as expected. However, if I log out (then refresh while logged out), the problem reappears until I reload again. If I only log out then log back in the problem does not reappear due, I think, in part to the fact the app does not reset as described here.
Why does A work? But not B? And what modifications must I make to B to get it to work? (Because I want to store the widgets
from the root/widgets/
path and not have to store that detail under the users/...
path.
My current (unproven) theory is that the in the case of B (when the URL is constant/static, i.e., widgets/
) firebase-query
gets involved in some sort of race condition; and only fetches the data after some lifecycle event and doesn't attempt to re-fetch the data. On the other hand, the firebase-query
does attempt to re-fetch when the path is dynamically updated based on the databinding in the path
attribute (i.e., path="users/[[user.uid]]/widgets"
). Is this theory correct? Or is there some other cause? Do I need to imperatively fetch the data after some event? If so, how can I accomplish all this?
I have tried the following ideas without success.
Cuser: {
type: Object,
notify: true,
observer: '_userChanged',
},
_userChanged: function() {
this.$.query.path = 'widgets';
var items = this.$.query.ref.child('widgets');
this.set('items', items);
},
D
<firebase-query
id="query"
...
path="[[path]]"
data="{{items}}">
</firebase-query>
<script>
...
properties: {
path: {
type: String,
value: function() {
return 'widgets';
},
}
},
...
</script>
Also, on the Polymer Slack Site, @will-in-china says:
I have had problems with the data loading the first time, I found that if i don't have more than one reference to the same path, i dont get this issue.
I'm not sure what that means in this context as I only have one reference in my element (and app) to the path path="widgets"
inside a firebase-query
element.
Upvotes: 0
Views: 223
Reputation: 66
I'm coming late but I resolve this using dom-if condition if user this prevent make a request if no are an user authenticate
Upvotes: -1
Reputation: 1
"When using A, I expect to see the items object populate, but instead the items object is null. However, if I refresh the browser manually (without logging out) the element behaves as expected. However, if I log out (then refresh while logged out), the problem reappears until I reload again."
I'm seeing similar behavior in my app. In my case, it is related to firebase-auth and firebase-query race conditions. In my case,
When I login, the firebase-auth is firing at the same time/after firebase-query. In this case, my query is rejected because of invalid permission - I am querying before being authenticated. Error log excerpt:
"detail: Error: permission_denied at /parents: Client doesn't have permission to access the desired data. …, type: "error", target: firebase-query .... firebase-query does not retry after authentication is complete. I don't know if this is a bug.
When I refresh after logging in, since I am already authenticated, the query is successful.
To debug this issue, I added a on-error handler to print out the permissions. To get around this issue, I am using the disabled property. When the page is first loaded, all queries are disabled. Only when authentication is successful, I toggle "disabled" at which point queries fire successfully.
signIn: function(){
var email = this.user.email;
var password = this.user.password;
this.$.auth.signInWithEmailAndPassword(email, password)
.then(function(response){
self.disabled = false;
// console.log('signin', response);
})
.catch(function(error){
console.log('auth-element:signIn error is', error.detail);
})
.then(function(){
// call other functions
});
},
handleError: function(error){
console.log('error message', error.detail.message);
},
<firebase-query
id = "query"
app-name="my-app"
path = "/shoeboxes"
data = "{{datauid}}"
on-error="handleError"
disabled="{{disabled}}">
</firebase-query>
Hope this helps. Basically, I'm finding that with polymer and firebase, promises are better than automagical bindings...
Upvotes: 0
Reputation: 6289
i dont think this is your specific issue but it may be similar in that after a login -> setNewRoute(nextPage) i did not get a render and i changed the subsequent template ( Iron-Ajax ) to fire manually rather than via the observer.
loggon: function parseLogin(user, password) {
...
Parse.User.logIn(_user, _pass).then(function() {
page('/channels');
---
channels.render ...
_render: function() {
console.log('_render');
this.$.get_channlinq.headers = hdr;
//xhr params
var body = this._setQry(this.params.channelId);
this.$.get_channlinq.body = JSON.stringify(body);
//fetch , load , template will render
this.$.get_channlinq.generateRequest();
Upvotes: 0