Skip to content

Commit f1b3595

Browse files
authored
feat(firestoreConnect): reconnect when query params change @danleavitt0
firestoreConnect reconnect when query params change
2 parents ab6aac7 + 5587402 commit f1b3595

File tree

2 files changed

+83
-75
lines changed

2 files changed

+83
-75
lines changed

src/firestoreConnect.js

Lines changed: 54 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
33
import hoistStatics from 'hoist-non-react-statics'
44
import { wrapDisplayName } from 'recompose'
55
import { createCallable } from './utils'
6+
import { isEqual } from 'lodash'
67

78
/**
89
* @name createFirestoreConnect
@@ -22,70 +23,68 @@ import { createCallable } from './utils'
2223
* // use the firebaseConnect to wrap a component
2324
* export default firestoreConnect()(SomeComponent)
2425
*/
25-
export const createFirestoreConnect = (storeKey = 'store') =>
26-
(dataOrFn = []) =>
27-
WrappedComponent => {
28-
class FirestoreConnect extends Component {
29-
static wrappedComponent = WrappedComponent
30-
static displayName = wrapDisplayName(WrappedComponent, 'FirestoreConnect')
31-
static contextTypes = {
32-
[storeKey]: PropTypes.object.isRequired
33-
}
26+
export const createFirestoreConnect = (storeKey = 'store') => (
27+
dataOrFn = []
28+
) => WrappedComponent => {
29+
class FirestoreConnect extends Component {
30+
static wrappedComponent = WrappedComponent
31+
static displayName = wrapDisplayName(WrappedComponent, 'FirestoreConnect')
32+
static contextTypes = {
33+
[storeKey]: PropTypes.object.isRequired
34+
}
3435

35-
prevData = null
36-
store = this.context[storeKey]
36+
prevData = null
37+
store = this.context[storeKey]
3738

38-
componentWillMount () {
39-
const { firebase, firestore } = this.store
40-
if (firebase.firestore && firestore) {
41-
// Allow function to be passed
42-
const inputAsFunc = createCallable(dataOrFn)
43-
this.prevData = inputAsFunc(this.props, this.store)
39+
componentWillMount () {
40+
const { firebase, firestore } = this.store
41+
if (firebase.firestore && firestore) {
42+
// Allow function to be passed
43+
const inputAsFunc = createCallable(dataOrFn)
44+
this.prevData = inputAsFunc(this.props, this.store)
4445

45-
firestore.setListeners(this.prevData)
46-
}
47-
}
46+
firestore.setListeners(this.prevData)
47+
}
48+
}
4849

49-
componentWillUnmount () {
50-
const { firebase, firestore } = this.store
51-
if (firebase.firestore && this.prevData) {
52-
firestore.unsetListeners(this.prevData)
53-
}
54-
}
50+
componentWillUnmount () {
51+
const { firebase, firestore } = this.store
52+
if (firebase.firestore && this.prevData) {
53+
firestore.unsetListeners(this.prevData)
54+
}
55+
}
5556

56-
// TODO: Re-attach listeners on query path change
57-
// componentWillReceiveProps (np) {
58-
// const { firebase, dispatch } = this.context.store
59-
// const inputAsFunc = createCallable(dataOrFn)
60-
// const data = inputAsFunc(np, firebase)
61-
//
62-
// // Handle a data parameter having changed
63-
// if (!isEqual(data, this.prevData)) {
64-
// this.prevData = data
65-
// // UnWatch all current events
66-
// unWatchEvents(firebase, dispatch, this._firebaseEvents)
67-
// // Get watch events from new data
68-
// this._firebaseEvents = getEventsFromInput(data)
69-
// // Watch new events
70-
// watchEvents(firebase, dispatch, this._firebaseEvents)
71-
// }
72-
// }
57+
// TODO: Re-attach listeners on query path change
58+
componentWillReceiveProps (np) {
59+
const { firebase, firestore } = this.store
60+
const inputAsFunc = createCallable(dataOrFn)
61+
const data = inputAsFunc(np, this.store)
7362

74-
render () {
75-
const { firebase, firestore } = this.store
76-
return (
77-
<WrappedComponent
78-
{...this.props}
79-
{...this.state}
80-
firebase={{ ...firebase, ...firebase.helpers }}
81-
firestore={firestore}
82-
/>
83-
)
84-
}
63+
// Handle a data parameter having changed
64+
if (firebase.firestore && !isEqual(data, this.prevData)) {
65+
this.prevData = data
66+
// UnWatch all current events
67+
firestore.unsetListeners(this.prevData)
68+
// Watch new events
69+
firestore.setListeners(this.prevData)
8570
}
71+
}
8672

87-
return hoistStatics(FirestoreConnect, WrappedComponent)
73+
render () {
74+
const { firebase, firestore } = this.store
75+
return (
76+
<WrappedComponent
77+
{...this.props}
78+
{...this.state}
79+
firebase={{ ...firebase, ...firebase.helpers }}
80+
firestore={firestore}
81+
/>
82+
)
8883
}
84+
}
85+
86+
return hoistStatics(FirestoreConnect, WrappedComponent)
87+
}
8988

9089
/**
9190
* @name firestoreConnect

tests/unit/firestoreConnect.spec.js

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import ReactDOM from 'react-dom'
44
import TestUtils from 'react-addons-test-utils'
55
import reactReduxFirebase from '../../src/enhancer'
66
import { createStore, compose, combineReducers } from 'redux'
7-
import firestoreConnect, { createFirestoreConnect } from '../../src/firestoreConnect'
7+
import firestoreConnect, {
8+
createFirestoreConnect
9+
} from '../../src/firestoreConnect'
810

911
describe('firestoreConnect', () => {
1012
class Passthrough extends Component {
@@ -25,7 +27,8 @@ describe('firestoreConnect', () => {
2527
cloneElement(this.props.children, {
2628
testProp: this.state.test,
2729
dynamicProp: this.state.dynamic
28-
}))
30+
})
31+
)
2932
}
3033
}
3134

@@ -37,23 +40,26 @@ describe('firestoreConnect', () => {
3740
store: PropTypes.object,
3841
children: PropTypes.node
3942
}
40-
const fakeReduxFirestore = (instance, otherConfig) => next =>
41-
(reducer, initialState, middleware) => {
42-
const store = next(reducer, initialState, middleware)
43-
store.firestore = { listeners: {} }
44-
return store
45-
}
43+
const fakeReduxFirestore = (instance, otherConfig) => next => (
44+
reducer,
45+
initialState,
46+
middleware
47+
) => {
48+
const store = next(reducer, initialState, middleware)
49+
store.firestore = { listeners: {} }
50+
return store
51+
}
4652

4753
const createContainer = () => {
4854
const createStoreWithMiddleware = compose(
4955
reactReduxFirebase(Firebase, { userProfile: 'users' }),
5056
fakeReduxFirestore(Firebase)
5157
)(createStore)
52-
const store = createStoreWithMiddleware(combineReducers({ firestore: (state = {}) => state }))
58+
const store = createStoreWithMiddleware(
59+
combineReducers({ firestore: (state = {}) => state })
60+
)
5361

54-
@firestoreConnect((props) => [
55-
`test/${props.dynamicProp}`
56-
])
62+
@firestoreConnect(props => [`test/${props.dynamicProp}`])
5763
class Container extends Component {
5864
render () {
5965
return <Passthrough {...this.props} />
@@ -85,21 +91,22 @@ describe('firestoreConnect', () => {
8591
})
8692

8793
it('does not change watchers props changes that do not change listener paths', () => {
88-
const { parent } = createContainer()
89-
parent.setState({ test: 'somethingElse' })
90-
// expect(parent.context.store).to.equal(store)
94+
const { container, store } = createContainer()
95+
container.setState({ test: 'somethingElse' })
96+
expect(container.context.store).to.equal(store)
9197
})
9298

9399
it('reapplies watchers when props change', () => {
94-
const { parent } = createContainer()
95-
parent.setState({
100+
const { container, store } = createContainer()
101+
container.setState({
96102
dynamic: 'somethingElse'
97103
})
98-
// expect(parent.context.store).to.equal(store)
104+
expect(container.context.store).to.equal(store)
99105
})
100106

101107
describe('sets displayName static as ', () => {
102-
describe('FirestoreConnect(${WrappedComponentName}) for', () => { // eslint-disable-line no-template-curly-in-string
108+
describe('FirestoreConnect(${WrappedComponentName}) for', () => {
109+
// eslint-disable-line no-template-curly-in-string
103110
it('standard components', () => {
104111
class TestContainer extends Component {
105112
render () {
@@ -108,7 +115,9 @@ describe('firestoreConnect', () => {
108115
}
109116

110117
const containerPrime = firestoreConnect()(TestContainer)
111-
expect(containerPrime.displayName).to.equal(`FirestoreConnect(TestContainer)`)
118+
expect(containerPrime.displayName).to.equal(
119+
`FirestoreConnect(TestContainer)`
120+
)
112121
})
113122

114123
it('string components', () => {

0 commit comments

Comments
 (0)