Skip to content
This repository was archived by the owner on Jun 16, 2022. It is now read-only.

Commit 7fb4abb

Browse files
committed
added value, list and user
added umd build
0 parents  commit 7fb4abb

File tree

14 files changed

+4511
-0
lines changed

14 files changed

+4511
-0
lines changed

.babelrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"presets": [
3+
[
4+
"env",
5+
{
6+
"targets": {
7+
"chrome": 49
8+
},
9+
"modules": false
10+
}
11+
]
12+
]
13+
}

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
dist/

.eslintrc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"extends": [
3+
"standard"
4+
],
5+
"env": {
6+
"node": true,
7+
"jest": true
8+
},
9+
"parserOptions": {
10+
"ecmaVersion": 2017,
11+
"ecmaFeatures": {
12+
"templateStrings": true,
13+
"classes": true
14+
}
15+
},
16+
"plugins": [
17+
"react"
18+
],
19+
"rules": {
20+
},
21+
"globals": {
22+
}
23+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
dist/

.npmignore

Whitespace-only changes.

LICENSE

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Copyright 2018 Ronald Chen
2+
3+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4+
5+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
react-firebase-fns
2+
==================
3+
4+
`react-firebase-fns` [Firebase](https://firebase.google.com/)'s [JavaScript SDK](https://firebase.google.com/docs/web/setup) turned into declarative [React](https://github.com/facebook/react) components.
5+
6+
Components
7+
----------
8+
9+
### Value
10+
Watch a [Realtime Database](https://firebase.google.com/docs/database/) value. Equivalent to https://firebase.google.com/docs/database/web/read-and-write#listen_for_value_events
11+
```js
12+
<Value
13+
path="/realtime/database/path"
14+
>{(val) =>
15+
{/* val is the value from dataSnapshot.val() */}
16+
}</Value>
17+
```
18+
19+
### List
20+
Watch a [Realtime Database](https://firebase.google.com/docs/database/) list. Equivalent to https://firebase.google.com/docs/database/web/lists-of-data#listen_for_child_events
21+
```js
22+
<List
23+
path="/realtime/database/list"
24+
25+
orderBy="child | key | value"
26+
// orderBy="child" is optional when orderByChild is set, but orderByChild is required when orderBy="child"
27+
// orderByChild is ignored when orderBy is set to anything other than child
28+
orderByChild="child key or path"
29+
30+
startAt="value"
31+
startAtKey="optional key"
32+
33+
endAt="value"
34+
endAtKey="optional key"
35+
36+
equalTo="value"
37+
equalToKey="optional key"
38+
39+
limitToFirst="number"
40+
limitToLast="number"
41+
>{(list) =>
42+
{/* list is updated on child_added, child_removed, and child_changed events */}
43+
}</List>
44+
```
45+
46+
### User
47+
A user state provider for [Authentication](https://firebase.google.com/docs/auth/). Equivalent to https://firebase.google.com/docs/auth/web/start#set_an_authentication_state_observer_and_get_user_data
48+
49+
Unlike other components, User is a [React Context](https://reactjs.org/docs/context.html#reactcreatecontext) with a Provider and Consumer.
50+
```js
51+
<User.Provider>
52+
53+
<SomeComponents>
54+
<DeeplyNested>
55+
56+
<User.Consumer>{(user) =>
57+
{/* user will be undefined if not logged in */}
58+
}</User.Consumer>
59+
60+
</DeeplyNested>
61+
</SomeComponents>
62+
63+
</User.Provider>
64+
```
65+
66+
Missing components?
67+
-------------------
68+
The entire SDK won't be exposed in this library. Only the parts with a realtime aspect make sense.
69+
70+
The following is not implemented yet. Make a pull request? ❤️
71+
### Realtime Database
72+
* [Connection state](https://firebase.google.com/docs/database/web/offline-capabilities#section-connection-state)
73+
* [Presence](https://firebase.google.com/docs/database/web/offline-capabilities#section-presence)
74+
### Cloud Firestore
75+
* [Realtime updates](https://firebase.google.com/docs/firestore/query-data/listen)
76+
### Storage
77+
* [Upload progress](https://firebase.google.com/docs/storage/web/upload-files#monitor_upload_progress)
78+
79+
Installation
80+
------------
81+
```
82+
npm install --save react-firebase-fns
83+
```
84+
85+
### Global Firebase
86+
Configure Firebase as usual and `react-firebase-fns` will use the global Firebase with:
87+
```js
88+
import {Value, List, User} from 'react-firebase-fns'
89+
```
90+
91+
### Provided Firebase application
92+
You can also pass in a Firebase application.
93+
```js
94+
import ReactFirebaseFns from 'react-firebase-fns'
95+
import Firebase from 'firebase'
96+
97+
const {Value, List, User} = ReactFirebaseFns(Firebase.initializeApp(config))
98+
```
99+
100+
Roadmap
101+
-------
102+
* add render prop
103+
* add component prop
104+
105+
Inspired by [react-fns](https://github.com/jaredpalmer/react-fns).
106+
107+
Ronald Chen [@pyrolistical](https://twitter.com/pyrolistical)

index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const Firebase = require('firebase')
2+
3+
const Value = require('./value')
4+
const List = require('./list')
5+
const User = require('./user')
6+
7+
module.exports = (Firebase) => {
8+
return {
9+
Value: Value(Firebase),
10+
List: List(Firebase),
11+
User: User(Firebase)
12+
}
13+
}
14+
15+
const globalFirebaseIntances = module.exports(Firebase)
16+
Object.assign(module.exports, globalFirebaseIntances)

list.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
const {Component} = require('react')
2+
3+
const ORDER_BY_TYPES = [
4+
'child',
5+
'key',
6+
'priority',
7+
'value'
8+
]
9+
10+
module.exports = (Firebase) => class extends Component {
11+
constructor (props) {
12+
super(props)
13+
14+
this.state = {
15+
list: {}
16+
}
17+
18+
this.setupListener = () => {
19+
const {path, startAt, startAtKey, endAt, endAtKey, equalTo, equalToKey, limitToFirst, limitToLast} = this.props
20+
let {orderBy, orderByChild} = this.props
21+
this.reference = Firebase.database().ref(path)
22+
if (!orderBy && orderByChild) {
23+
orderBy = 'child'
24+
}
25+
if (orderBy) {
26+
switch (orderBy) {
27+
case 'child':
28+
if (!orderByChild) {
29+
throw new Error('orderByChild must be used when orderBy="child"')
30+
}
31+
this.reference = this.reference.orderByChild(orderByChild)
32+
break
33+
case 'key':
34+
this.reference = this.reference.orderByKey()
35+
break
36+
case 'priority':
37+
this.reference = this.reference.orderByPriority()
38+
break
39+
case 'value':
40+
this.reference = this.reference.orderByValue()
41+
break
42+
default:
43+
throw new Error(`orderBy must be one of [${ORDER_BY_TYPES.join(', ')}] but got ${orderBy}`)
44+
}
45+
}
46+
if (startAt) {
47+
this.reference = this.reference.startAt(startAt, startAtKey)
48+
}
49+
if (endAt) {
50+
this.reference = this.reference.endAt(endAt, endAtKey)
51+
}
52+
if (equalTo) {
53+
this.reference = this.reference.equalTo(equalTo, equalToKey)
54+
}
55+
if (limitToFirst) {
56+
this.reference = this.reference.limitToFirst(Number.parseInt(limitToFirst, 10))
57+
}
58+
if (limitToLast) {
59+
this.reference = this.reference.limitToLast(Number.parseInt(limitToLast, 10))
60+
}
61+
this.onChildAddedListener = this.reference.on('child_added', (snapshot) => {
62+
this.setState({
63+
list: Object.assign({}, this.state.list, {
64+
[snapshot.key]: snapshot.val()
65+
})
66+
})
67+
})
68+
this.onChildRemovedListener = this.reference.on('child_removed', (snapshot) => {
69+
const nextList = {}
70+
for (const key in this.state.list) {
71+
if (key !== snapshot.key) {
72+
nextList[key] = this.state.list[key]
73+
}
74+
}
75+
this.setState({
76+
list: nextList
77+
})
78+
})
79+
this.onChildChangedListener = this.reference.on('child_changed', (snapshot) => {
80+
this.setState({
81+
list: Object.assign({}, this.state.list, {
82+
[snapshot.key]: snapshot.val()
83+
})
84+
})
85+
})
86+
}
87+
88+
this.cleanUpListener = () => {
89+
if (!this.reference) {
90+
return
91+
}
92+
this.reference.off('child_added', this.onChildAddedListener)
93+
this.reference.off('child_removed', this.onChildAddonChildRemovedListeneredListener)
94+
this.reference.off('child_changed', this.onChildChangedListener)
95+
this.reference = undefined
96+
}
97+
}
98+
99+
componentDidMount () {
100+
this.setupListener()
101+
}
102+
103+
componentDidUpdate ({path: prevPath, limit: prevLimit = 16}) {
104+
const {path, limit = 16} = this.props
105+
if (path !== prevPath || limit !== prevLimit) {
106+
this.cleanUpListener()
107+
this.setState({
108+
list: {}
109+
})
110+
this.setupListener()
111+
}
112+
}
113+
114+
componentWillUnmount () {
115+
this.cleanUpListener()
116+
}
117+
118+
render () {
119+
return this.props.children(this.state.list)
120+
}
121+
}

0 commit comments

Comments
 (0)