tiberiuc / redux-react-firebase

Use Firebase with React and Redux in ES6
MIT License
248 stars 36 forks source link

[Question] How to fetch a single resource item based on its field value #49

Closed gazpachu closed 7 years ago

gazpachu commented 7 years ago

In my firebase database I have a pages resource, which takes care of storing the data for the static pages of my app. It looks like this:

screen shot 2016-12-30 at 09 58 14

As you can see, I have a slug attribute, which I intend to match with the browser URL to retrieve the page data when the user lands on /about.

In the docs, I can see how to request a specific resource item using the ID, but how can I do it with a field value? In my case the slug value:

@firebase(
  props => ([
    `pages/${search by slug}`
  ])
)
@connect(
  (state, props) => ({
    todo: dataToJs(state.firebase, `pages/${search by slug}`)
  })
)
RahavLussato commented 7 years ago

@gazpachu you can use queries for that : equalTo/startAt/endAt it depends on your case

@firebase(
  props => ([
    `pages#queryId=slugsSearch&orderByChild=slug&equalTo=${search by slug}`
  ])
)
@connect(
  (state, props) => ({
    todo: dataToJs(state.firebase, `pages/${search by slug}`)
  })
)
gazpachu commented 7 years ago

Thanks @RahavLussato.

This seems to work:

@firebase(
  props => ([
    `pages#orderByChild=slug&equalTo=about`
  ])
)
@connect(
  (state, props) => ({
    pages: dataToJS(state.firebase, 'pages')
  })
)

Now I also get a Warning: FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "slug" at /pages to your security rules for better performance

Is there a way to fix that warning?

RahavLussato commented 7 years ago

@gazpachu you can add index on firebase console on rules tab. the warning is not related to our lib, its from firebase.

@tiberiuc please close that.

gazpachu commented 7 years ago

Cool, I didn't know the correct way to update it in the rules. This is how it seems to work:

"pages": {
        ".indexOn": ["slug"]
      }
gazpachu commented 7 years ago

Another related question before this gets closed. What's the best practice (and safest way) to access this.props.location.pathname inside the firebase decorator? I was using this in the constructor to get the slug:

// Assuming the user is in /about/research, this.slug will be 'research'
let path = this.props.location.pathname.split('/');
this.slug = path[path.length-1];

How can I put that inside the firebase decorator? My aim is to get the last bit from the browser URL to send it as a slug to firebase:

@firebase(
 let pageSlug = ...
  props => ([
    `pages#orderByChild=slug&equalTo=${pageSlug}`
  ])
)
@connect(
  (state, props) => ({
    pages: dataToJS(state.firebase, 'pages')
  })
)
gazpachu commented 7 years ago

I fixed it without using this.props, although I'm not sure this is very safe... pages#orderByChild=slug&equalTo=${window.location.href.substr(window.location.href.lastIndexOf('/') + 1)}

but it would be nice to know how to do it with this.props

RahavLussato commented 7 years ago

@gazpachu i think it's better to use props, You can write a function that will get the url from props and will do the split stuff, and then put the function inside the decorator.

RahavLussato commented 7 years ago

@gazpachu can we close this ?

gazpachu commented 7 years ago

Yes @RahavLussato thanks