Created
May 14, 2019 17:31
-
-
Save samcorcos/e387e3368322bb94cf231cb76ea07ed7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
/** | |
* The goal of this component is to wrap another component and give it some data from the | |
* database while maintaining state and bindings and significantly cutting down on | |
* boilerplate. | |
* | |
* This component expects a function | |
* See [this article](https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9) | |
* for more information on why function-as-child components are awesome for this use case | |
* | |
* For basic usage of this component, see [this gist](https://gist.github.com/samcorcos/8e58decdaea1181099c22d2e149efdb0) | |
* | |
* @param {Object} props.query - the reference to the database query. e.g. db.collection('orders') | |
* @param {function} props.children - props.children must be a function | |
*/ | |
class Data extends React.Component { | |
constructor (props) { | |
super(props) | |
this.ref = props.query | |
this.unsubscribe = null | |
this.state = { | |
loading: true, | |
data: {} | |
} | |
} | |
componentDidMount = () => { | |
this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate) | |
} | |
componentWillUnmount = () => { | |
this.unsubscribe() | |
} | |
componentDidUpdate = (prevProps) => { | |
// if the query changes, update the listener | |
// https://firebase.google.com/docs/reference/js/firebase.firestore.Query#isequal | |
if (!prevProps.query.isEqual(this.props.query)) { | |
this.ref = this.props.query | |
this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate) | |
} | |
} | |
onCollectionUpdate = (snap) => { | |
/* if the snapshot has a `forEach` function, the result is from a collection. otherwise, | |
it's a document */ | |
if (snap.forEach) { | |
const temp = {} | |
snap.forEach((doc) => { | |
temp[doc.id] = { | |
id: doc.id, | |
...doc.data() | |
} | |
}) | |
this.setState({ | |
data: temp, | |
loading: false | |
}) | |
} else { | |
this.setState({ | |
data: { | |
id: snap.id, | |
...snap.data() | |
}, | |
loading: false | |
}) | |
} | |
} | |
render () { | |
return this.props.children(this.state) | |
} | |
} | |
export default Data |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment