Queries

Creating

Firebase Real Time Database queries can be created in two ways:

  • Automatically - Using firebaseConnect HOC (manages mounting/unmounting)
  • Manually - Using watchEvents or watchEvent (requires managing of listeners)

Automatically

firebaseConnect accepts an array of paths for which to create queries. When listening to paths, it is possible to modify the query with any of Firebase's included query methods.

NOTE: By default the results of queries are stored in redux under the path of the query. If you would like to change where the query results are stored in redux, use storeAs (more below).

Below are examples using Firebase query methods as well as other methods that are included (such as 'populate').

firebaseConnect is a Higher Order Component (wraps a provided component) that attaches listeners to relevant paths on Firebase when mounting, and removes them when unmounting.

storeAs

Data is stored in redux under the path of the query for convince. This means that two different queries to the same path (i.e. todos) will both place data into state.data.todos even if their query parameters are different. If you would like to store your query somewhere else in redux, use storeAs:

compose(
  firebaseConnect([
    {
      path: 'todos',
      storeAs: 'myTodos', // place in redux under "myTodos"
      queryParams: ['orderByChild=createdBy', 'equalTo=123someuid'],
    }
    {
      path: 'todos',
      queryParams: ['limitToFirst=20'],
    }
  ]),
  connect((state) => ({
    myTodos: state.firebase.data.myTodos, // due to storeAs
    allTodos: state.firebase.data.todos // state.firebase.data.todos since no storeAs
  }))
)

Manually

Queries can be created manually by using watchEvent or watchEvents. This is useful to load data on some event such as a button click.

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { withFirebase, isLoaded, isEmpty } from 'react-redux-firebase'

const Todos = ({ firebase }) => {
  // Build Todos list if todos exist and are loaded
  const todosList = !isLoaded(todos)
    ? 'Loading'
    : isEmpty(todos)
      ? 'Todo list is empty'
      : Object.keys(todos).map(
          (key, id) => <TodoItem key={key} id={id} todo={todos[key]}/>
        )
  return (
    <div>
      <h1>Todos</h1>
      <ul>
        {todosList}
      </ul>
      <button onClick={() => firebase.watchEvent('value', 'todos')}>
        Load Todos
      </button>
    </div>
  )
}

export default compose(
  withFirebase, // or firebaseConnect()
  connect(
    (state) => ({
      todos: state.firebase.data.todos,
      // profile: state.firebase.profile // load profile
    })
  )
)(Todos)

Fun Fact - firebaseConnect actually calls watchEvents internally on component mount/unmount and when props change

Ordered vs Data (by key)

data

In order to get data from state by key, use data.

Examples

  1. Get an object of projects by key
compose(
  firebaseConnect(props => [
    { path: 'projects' }
  ]),
  connect((state, props) => ({
    projects: state.firebase.data.projects,
  }))
)

ordered

In order to get ordered data, use orderedToJS

Examples

  1. Get list of projects ordered by key
compose(
  firebaseConnect(props => [
    { path: 'projects', queryParams: ['orderByKey'] }
  ]),
  connect((state, props) => ({
    projects: state.firebase.ordered.projects,
  }))
)

Populate

Populate allows you to replace IDs within your data with other data from Firebase. This is very useful when trying to keep your data flat. Some would call it a join, but it was modeled after the mongo populate method.

Visit Populate Section for full documentation.

Types of Queries

There are multiple types of queries

once

To load a firebase location once instead of binding, the once option can be used:

Internal Method: orderByPriority

firebaseConnect([
  { type: 'once', path: '/todos' }
])

Query Params

orderByChild

To order the query by a child within each object, use orderByChild.

Internal Method: orderByChild

Example

Ordering a list of todos by the text parameter of the todo item (placing them in alphabetical order).

firebaseConnect([
  '/todos#orderByChild=text'
  // { path: '/todos', queryParams: [ 'orderByChild=text' ]} // object notation
])

orderByKey

Order a list by the key of each item. Since push keys contain time, this is also a way of ordering by when items were created.

Internal Method: orderByKey

Example

Ordering a list of todos based on their key (puts them in order of when they were created)

firebaseConnect([
  '/todos#orderByKey'
  // { path: '/todos', queryParams: [ 'orderByKey' ]} // object notation
])

orderByValue

Order a list by the value of each object. Internally runs

Internal Method: orderByValue

Example

Ordering a list of score's based on score's value

firebaseConnect([
  `scores#orderByValue`
  // { path: '/scores', queryParams: [ 'orderByValue' ] } // object notation
])

orderByPriority

Order a list by the priority of each item.

Internal Method: orderByPriority

Example

Ordering a list based on priorities

firebaseConnect([
  `scores#orderByPriority`
  // { path: '/scores', queryParams: [ 'orderByPriority' ] } // object notation
])

limitToFirst

Limit query results to the first n number of results.

Internal Method: limitToFirst

Examples

  1. Displaying only the first todo item

    firebaseConnect([
     '/todos#limitToFirst'
     // { path: '/todos', queryParams: [ 'limitToFirst=1' ] } // object notation
    ])
    
  2. Displaying only the first 10 todo items

    firebaseConnect([
     '/todos#limitToFirst=10'
     // { path: '/todos', queryParams: [ 'orderByChild=createdBy', 'equalTo=123' ] } // object notation
    ])
    

limitToLast

Limit query results to the last n number of results

Internal Method: limitToLast

Examples

  1. Only the last todo item

    firebaseConnect([
     '/todos#limitToLast'
     // { path: '/todos', queryParams: [ 'limitToLast' ] } // object notation
    ])
    
  2. Only the last 10 todo items

    firebaseConnect([
     '/todos#limitToLast=10'
     // { path: '/todos', queryParams: [ 'limitToLast=10' ] } // object notation
    ])
    

startAt

Limit query results to include a range starting at a specific number

Internal Method: limitToLast

Examples

  1. Starting at the fifth item
    firebaseConnect([
     'todos#startAt=5&limitToFirst=2'
     // { path: '/todos', queryParams: [ 'startAt=5', 'limitToFirst=2' ] } // object notation
    ])
    
  2. Paginate results
    firebaseConnect([
     'todos#startAt=5&limitToFirst=10'
     // { path: '/todos', queryParams: [ 'startAt=5', 'limitToFirst=10' ] } // object notation
    ])
    

endAt

Examples

  1. Usage with startAt
    firebaseConnect([
    'todos#orderByChild=added&startAt=1&endAt=5'
    // { path: '/todos', queryParams: [ 'orderByChild=added', 'startAt=1', 'endAt=5' ] } // object notation
    ])
    

equalTo

Limit query results with parameter equal to previous query method (i.e when used with orderByChild, it limits results with child equal to provided value). Internally runs Firebase's equalTo.

Parsing

The following are internally parsed:

  • null
  • boolean
  • number

This means the actual value will be parsed instead of the string containing the value. If you do not want this to happen, look at the notParsed query parameter below.

Examples

  1. Order by child parameter
    firebaseConnect([
    'todos#orderByChild=createdBy&equalTo=ASD123',
    // { path: '/todos', queryParams: [ 'orderByChild=createdBy', 'equalTo=ASD123' ] } // object notation
    ])
    

notParsed

Can be used to keep internal parsing from happening. Useful when attempting to search a number string using equalTo

Examples

  1. Order by child parameter equal to a number string. Equivalent of searching for '123' (where as not using notParsed would search for children equal to 123)
    firebaseConnect([
    {
     path: '/todos',
     queryParams: [
       'orderByChild=createdBy',
       'notParsed', // keeps equalTo from automatically parsing
       'equalTo=123'
     ]
    }
    ])
    

storeAs

By default the results of queries are stored in redux under the path of the query. If you would like to change where the query results are stored in redux, use storeAs:

Examples

  1. Querying the same path with different query parameters
compose(
  firebaseConnect(props => [
    { path: 'projects' }
    { path: 'projects', storeAs: 'myProjects', queryParams: ['orderByChild=uid', '123'] }
  ]),
  connect(({ firebase }, props) => ({
    projects: populatedDataToJS(firebase, 'projects'),
    myProjects: populatedDataToJS(firebase, 'myProjects'), // use storeAs path to gather from redux
  }))
)

results matching ""

    No results matching ""