Skip to content

Commit

Permalink
v3.6.0 (#966)
Browse files Browse the repository at this point in the history
* feat(types): add database and firestore statics (#957) - @msutkowski, @themindoverall, @phryneas
* feat(types): add type predicate to `isLoaded` (#956) - @lukeKonopka
* chore(docs): formatting fixes in firestore docs section (#959) - @gregfenton
* feat(docs): add firestore populate docs (#954) - @harveychow

Co-authored-by: gregfenton <greg.fenton@gmail.com>
Co-authored-by: Matt Sutkowski <msutkowski@gmail.com>
Co-authored-by: Chris Serino <themindoverall@gmail.com>
Co-authored-by: Harvey Chow <hchow83@gmail.com>
Co-authored-by: Luke Konopka <g00bm4n@gmail.com>
  • Loading branch information
6 people committed Jun 19, 2020
1 parent e242b41 commit 46ca1a8
Show file tree
Hide file tree
Showing 12 changed files with 595 additions and 495 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x]
node-version: [10.x, 12.x, 14.x]
steps:
- name: Checkout code
uses: actions/checkout@v2
Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,16 @@ import React from 'react'
import PropTypes from 'prop-types'
import { get } from 'lodash'
import { useSelector } from 'react-redux'
import { useFirebaseConnect } from 'react-redux-firebase'
import { useFirebaseConnect, useFirebase } from 'react-redux-firebase'
import { useParams } from 'react-router-dom'

export default function Todo() {
const { todoId } = useParams() // matches todos/:todoId in route
const firebase = useFirebase()

useFirebaseConnect([
{ path: `todos/${todoId}` } // create todo listener
// `todos/${props.params.todoId}` // equivalent string notation
// `todos/${todoId}` // equivalent string notation
])

const todo = useSelector(
Expand Down Expand Up @@ -238,7 +239,7 @@ function TodosList() {
)
}

function Todos() {
export default function Todos() {
const firebase = useFirebase()

return (
Expand All @@ -251,9 +252,6 @@ function Todos() {
</div>
)
}

// Export enhanced component
export default Todos
```

## Firestore
Expand Down
28 changes: 10 additions & 18 deletions docs/api/firestoreConnect.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@

### Table of Contents

- [firestoreConnect][1]
- [Parameters][2]
- [Examples][3]
- [Parameters][4]
- [firestoreConnect][1]
- [Parameters][2]
- [Examples][3]
- [Parameters][4]

## firestoreConnect

**Extends React.Component**


Higher Order Component that automatically listens/unListens
to provided Cloud Firestore paths using React's Lifecycle hooks. Make sure you
have required/imported Cloud Firestore, including its reducer, before
have required/imported Cloud Firestore, including it's reducer, before
attempting to use. **Note** Populate is not yet supported.

### Parameters

- `queriesConfig` **([Array][6] \| [Function][7])** Array of objects or strings for paths to sync
from Firebase. Can also be a function that returns the array. The function
is passed the current props and the firebase object. (optional, default `[]`)
- `queriesConfig` **([Array][6] \| [Function][7])** Array of objects or strings for paths to sync
from Firebase. Can also be a function that returns the array. The function
is passed the current props and the firebase object. (optional, default `[]`)

### Examples

Expand Down Expand Up @@ -51,28 +50,21 @@ export default compose(
Returns **[Function][7]** Function which accepts a component to wrap and returns the
wrapped component
##
##
Render component wrapped in context
### Parameters
- `props` **[object][8]** Component props
- `props` **[object][8]** Component props
Returns **React.Component** Component wrapped in context
[1]: #firestoreconnect
[2]: #parameters
[3]: #examples
[4]: #parameters-1
[5]: https://react-redux-firebase.com/docs/api/firestoreConnect.html
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
211 changes: 104 additions & 107 deletions docs/firestore.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,38 +98,36 @@ Firestore queries can be created in the following ways:
`useFirestoreConnect` is a React hook that manages attaching and detaching listeners for you as the component mounts and unmounts.

#### Examples

1. Basic query that will attach/detach as the component passed mounts/unmounts. In this case we are setting a listener for the `'todos'` collection:

```js
import React from 'react'
import { useSelector } from 'react-redux'
import { useFirestoreConnect } from 'react-redux-firebase'

export default function SomeComponent() {
useFirestoreConnect([
{ collection: 'todos' } // or 'todos'
])
const todos = useSelector((state) => state.firestore.ordered.todos)
}
```
```js
import React from 'react'
import { useSelector } from 'react-redux'
import { useFirestoreConnect } from 'react-redux-firebase'

export default function SomeComponent() {
useFirestoreConnect([
{ collection: 'todos' } // or 'todos'
])
const todos = useSelector((state) => state.firestore.ordered.todos)
}
```

2. Props can be used as part of queries. In this case we will get a specific todo:

```js
import React from 'react'
import { useSelector } from 'react-redux'
import { useFirestoreConnect } from 'react-redux-firebase'

export default function SomeComponent({ todoId }) {
useFirestoreConnect(() => [
{ collection: 'todos', doc: todoId } // or `todos/${props.todoId}`
])
const todo = useSelector(
({ firestore: { data } }) => data.todos && data.todos[todoId]
)
}
```
```js
import React from 'react'
import { useSelector } from 'react-redux'
import { useFirestoreConnect } from 'react-redux-firebase'
export default function SomeComponent({ todoId }) {
useFirestoreConnect(() => [
{ collection: 'todos', doc: todoId } // or `todos/${props.todoId}`
])
const todo = useSelector(
({ firestore: { data } }) => data.todos && data.todos[todoId]
)
}
```

### Automatically with HOC {#firestoreConnect}

Expand All @@ -138,36 +136,35 @@ export default function SomeComponent({ todoId }) {
#### Examples

1. Basic query that will attach/detach as the component passed mounts/unmounts. In this case we are setting a listener for the `'todos'` collection:

```js
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase'

export default compose(
firestoreConnect(() => ['todos']), // or { collection: 'todos' }
connect((state, props) => ({
todos: state.firestore.ordered.todos
}))
)(SomeComponent)
```
```js
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase'
export default compose(
firestoreConnect(() => ['todos']), // or { collection: 'todos' }
connect((state, props) => ({
todos: state.firestore.ordered.todos
}))
)(SomeComponent)
```

2. Create a query based on props by passing a function. In this case we will get a specific todo:

```js
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase'

export default compose(
firestoreConnect((props) => [
{ collection: 'todos', doc: props.todoId } // or `todos/${props.todoId}`
]),
connect(({ firestore: { data } }, props) => ({
todos: data.todos && data.todos[todoId]
}))
)(SomeComponent)
```
```js
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase'

export default compose(
firestoreConnect((props) => [
{ collection: 'todos', doc: props.todoId } // or `todos/${props.todoId}`
]),
connect(({ firestore: { data } }, props) => ({
todos: data.todos && data.todos[todoId]
}))
)(SomeComponent)
```

## Manual {#manual}

Expand Down Expand Up @@ -281,58 +278,58 @@ By default the results of queries are stored in redux under the path of the quer
#### Examples

1. Querying the same path with different query parameters

```js
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase'
const myProjectsReduxName = 'myProjects'

compose(
firestoreConnect((props) => [
{ collection: 'projects' },
{
collection: 'projects',
where: [['uid', '==', '123']],
storeAs: myProjectsReduxName
}
]),
connect((state, props) => ({
projects: state.firestore.data.projects,
myProjects: state.firestore.data[myProjectsReduxName] // use storeAs path to gather from redux
}))
)
```

2. Set `useFirestoreConnect` for subcollections documents
For example, in Firestore cloud you have such message structure:
`chatMessages (collection) / chatID (document) / messages (collection) / messageID (document)`

You can't write the path in `useFirestoreConnect` like:

```js
useFirestoreConnect(`chatMessages/${chatID}/messages`)
```

You will have error:

`Queries with subcollections must use "storeAs" to prevent invalid store updates. This closley matches the upcoming major release (v1), which stores subcollections at the top level by default.`

Solution:
Use `subcollections` for 'messages' and `storeAs`.

````import { useFirestoreConnect } from 'react-redux-firebase'
useFirestoreConnect([
{
collection: 'chatMessages',
doc: chatID,
subcollections: [{ collection: 'messages' }],
storeAs: 'myMessages'
}
])```
```js
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase'
const myProjectsReduxName = 'myProjects'

compose(
firestoreConnect((props) => [
{ collection: 'projects' },
{
collection: 'projects',
where: ['uid', '==', '123'],
storeAs: myProjectsReduxName
}
]),
connect((state, props) => ({
projects: state.firestore.data.projects,
myProjects: state.firestore.data[myProjectsReduxName] // use storeAs path to gather from redux
}))
)
```

2. Set `useFirestoreConnect` for subcollections documents. For example, in Cloud Firestore you might have a message structure such as:

`chatMessages (collection) / chatID (document) / messages (collection) / messageID (document)`

You cannot write the path in `useFirestoreConnect` like:

```js
useFirestoreConnect(`chatMessages/${chatID}/messages`)
```

This will lead to the error:

`Queries with subcollections must use "storeAs" to prevent invalid store updates. This closley matches the upcoming major release (v1), which stores subcollections at the top level by default.`

**Solution**:

Use `subcollections` for `messages` and `storeAs`.

```js
import { useFirestoreConnect } from 'react-redux-firebase'
useFirestoreConnect([
{
collection: 'chatMessages',
doc: chatID,
subcollections: [{ collection: 'messages' }],
storeAs: 'myMessages'
}
])
```

## Populate {#populate}

Populate is supported for Firestore as of [v0.6.0 of redux-firestore](https://github.com/prescottprue/redux-firestore/releases/tag/v0.6.0). It was added [as part of issue #48](https://github.com/prescottprue/redux-firestore/issues/48).
````
23 changes: 23 additions & 0 deletions docs/populate.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,26 @@ const config = {
}
}
```

### Use with Firestore

To use populate with Firestore, just replace firebaseConnect with firestoreConnect with the corresponding charaters.

```javascript
import { firestoreConnect, populate } from 'react-redux-firebase';

const populates = [
{ child: 'owner', root: 'users', childAlias: 'ownerObj' }
]

const enhance = compose(
firestoreConnect([
{ collection: 'todos', populates }
]),
connect(
({ firebase }) => ({
todos: populate(firebase, 'todos', populates),
})
)
)
```
2 changes: 1 addition & 1 deletion examples/snippets/watchEvent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ render () {
}
```

**NOTE**: This is simplified functionality of what is available through [`firebaseConnect`](https://react-redux-firebase.com/docs/api/firebaseConnect.html) and {`useFirebaseConnect`](https://react-redux-firebase.com/docs/api/useFirebaseConnect.html).
**NOTE**: This is simplified functionality of what is available through [`firebaseConnect`](https://react-redux-firebase.com/docs/api/firebaseConnect.html) and [`useFirebaseConnect`](https://react-redux-firebase.com/docs/api/useFirebaseConnect.html).
Loading

0 comments on commit 46ca1a8

Please sign in to comment.