Skip to content

feat(utils): new utilities to simplify common queries #206

Open
@nt4f04uNd

Description

@nt4f04uNd

What is the feature?
Populates syntax sugar

What version would this apply to?
I wrote my examples on 2.2.6.

Do you have thoughts/examples on how the feature would be used (i.e. API)?
I have a bunch of ready functions I wrote on Typescript. I want you to include them into your library, or something like these ones, because current query structure is very annoying.

Here's a straightforward example, how I use them

import { IAppState } from 'src/store/rootReducer'
import { createFirestoreQueries, createPopulates, populateWithDocId, IMapStoreToProps } from 'myModule'
import { compose } from 'redux';

interface IProps extends
   IMapStateToProps,
   IMapDispatchToProps,
   IMapStateToProps2 { }

interface IMapStateToProps {
   uid: string
}
interface IOwnProps { }
const mapStateToProps = (state: IAppState, ownProps: IOwnProps): IMapStateToProps => ({
   uid: state.firebase.auth.uid
});

interface IMapStateToProps2 {
   privateCollection: object
}
interface IOwnProps2 {
   uid: string
}

// just convinient to have an object, when you have a lot of populates in one firestoreConnect
const populates = {
   privateCollection: createPopulates(
      populateWithDocId('incomingRequests', 'users', 'profile')
   )
}
const mapStoreToProps = (ownProps: IOwnProps2): IMapStoreToProps[] => createFirestoreQueries({
   path: `users/${ownProps.uid}/private/friends/incomingRequests`, populates: populates.privateCollection
})
const mapStateToProps2 = (state: IAppState, ownProps: IOwnProps2): IMapStateToProps2 => ({
   privateCollection: populate(state.firestore, `users/${ownProps.uid}/private/friends/incomingRequests`, populates.privateCollection)
});

export default compose(
   connect(mapStateToProps, null) as any, // as any because something goes wrong in types and I'm getting strange error
   firestoreConnect(mapStoreToProps),
   connect(mapStateToProps2),
)(class Requests extends React.Component<IProps, IState> {

Description

Since I discovered that third argument in populate() from your lib can be a function, I started to write my sugar

createPopulates()

A higher order function. Basiclly is just accepts as many populates objects or populate functions and returns an array of them

Example:

const populates = createPopulates(
    populateWithDocId('incomingRequests', 'users', 'profile')
)

This is same as if you had written like this:

const populates = (...args: any) => [
    populateWithDocId('incomingRequests', 'users', 'profile')(args)
]

populateWithDocId()()

This function proceeds doc id to to the result of query as custom field

parameters:

  1. childCollection — name of collection which contains document
  2. rootCollection — name of collection which contains values to populate
  3. fieldName — alias name to stored field

Second invocation passes dataKey and originalData

createFirestoreQueries()

Creates an array of queries, accepts infinitely many objects of structure { path: <pathString>, populates: <resultOfCreatePopulates>}

Example:

const mapStoreToProps = (ownProps: IOwnProps2): IMapStoreToProps[] => createFirestoreQueries({
   path: `users/${ownProps.uid}/private/friends/incomingRequests`, populates: populates.privateCollection
})

This can be written as:

const mapStoreToProps = (ownProps: IOwnProps2): IMapStoreToProps[] => [{
collection: 'users', doc: ownProps.uid, subcollections: [{
      collection: 'private', doc: 'friends', subcollections: [{
         collection: 'incomingRequests'
      }]
   }],
   populates: populates.privateCollection
}]

pathOptions() ???

Alias of JSON.stringify()
For using in createFirestoreQueries()'s path

Basiclly you can add additional query params to path on every level.
I wrote this function, but now I doubt in her need.

parameters:

  1. options — object with additional query params, such as where or startAt

Example:

createFirestoreQueries({
   path: `users/${ownProps.uid}/private(${pathOptions({
      where: ['nicknameId', '==', 'example']
   })})/friends/incomingRequests`
})

It's replacement for

[{
   collection: 'users', doc: ownProps.uid, subcollections: [{
      collection: 'private', doc: 'friends', where: ['nicknameId', '==', 'example'], subcollections: [{
         collection: 'incomingRequests'
      }]
   }],
   populates: populates.privateCollection
}]

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions