Skip to content

Commit a2764a7

Browse files
authored
v0.5.0
* fix(query): `DOCUMENT_MODIFIED` action correctly updates data reducer when using nested collections in solution from @compojoom - #88 * fix(query): fixed issue where `limit` was not included in query name - #90 * feat(query): `storeAs` support for subcollections * feat(query): `where` now uses `=` in place of `::` within query string name (matches other query params)
2 parents e1051d4 + d2eb15b commit a2764a7

File tree

10 files changed

+59
-17
lines changed

10 files changed

+59
-17
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ Storing data under a different path within redux is as easy as passing the `stor
358358
},
359359
```
360360

361-
**NOTE:** Not yet supported inside of subcollections (only at the top level)
361+
**NOTE:** Usage of `"/"` and `"."` within `storeAs` can cause unexpected behavior when attempting to retrieve from redux state
362362

363363

364364
#### Other Firebase Statics

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-firestore",
3-
"version": "0.4.3",
3+
"version": "0.5.0",
44
"description": "Redux bindings for Firestore.",
55
"main": "lib/index.js",
66
"module": "es/index.js",

src/actions/firestore.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ const changeTypeToEventType = {
179179
function docChangeEvent(change, originalMeta = {}) {
180180
return {
181181
type: changeTypeToEventType[change.type] || actionTypes.DOCUMENT_MODIFIED,
182-
meta: { ...originalMeta, doc: change.doc.id },
182+
meta: { ...originalMeta, doc: change.doc.id, path: change.doc.ref.path },
183183
payload: {
184184
data: change.doc.data(),
185185
ordered: { oldIndex: change.oldIndex, newIndex: change.newIndex },

src/reducers/dataReducer.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,21 @@ export default function dataReducer(state = {}, action) {
4646
// Data to set to state is doc if doc name exists within meta
4747
const data = docName ? get(payload.data, docName) : payload.data;
4848
// Get previous data at path to check for existence
49-
const previousData = get(state, pathFromMeta(meta));
49+
const previousData = get(state, meta.storeAs || pathFromMeta(meta));
5050
// Set data (without merging) if no previous data exists or if there are subcollections
5151
if (!previousData || meta.subcollections) {
5252
// Set data to state immutabily (lodash/fp's setWith creates copy)
53-
return setWith(Object, pathFromMeta(meta), data, state);
53+
return setWith(Object, meta.storeAs || pathFromMeta(meta), data, state);
5454
}
5555
// Otherwise merge with existing data
5656
const mergedData = assign(previousData, data);
5757
// Set data to state (with merge) immutabily (lodash/fp's setWith creates copy)
58-
return setWith(Object, pathFromMeta(meta), mergedData, state);
58+
return setWith(
59+
Object,
60+
meta.storeAs || pathFromMeta(meta),
61+
mergedData,
62+
state,
63+
);
5964
case DOCUMENT_MODIFIED:
6065
case DOCUMENT_ADDED:
6166
return setWith(

src/reducers/orderedReducer.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ function writeCollection(collectionState, action) {
7272
return unionBy(collectionState, action.payload.ordered, 'id');
7373
}
7474

75-
// Handle subcollections
76-
if (meta.doc && meta.subcollections) {
75+
// Handle subcollections (only when storeAs is not being used)
76+
if (meta.doc && meta.subcollections && !meta.storeAs) {
7777
if (!size(collectionState)) {
7878
// Collection state does not already exist, create it with item containing
7979
// subcollection
@@ -91,11 +91,14 @@ function writeCollection(collectionState, action) {
9191
}),
9292
);
9393
}
94+
9495
if (meta.doc && size(collectionState)) {
95-
return updateItemInArray(collectionState, meta.doc, item =>
96+
// Update item in array (handling storeAs)
97+
return updateItemInArray(collectionState, meta.storeAs || meta.doc, item =>
9698
mergeObjects(item, action.payload.ordered[0]),
9799
);
98100
}
101+
99102
return action.payload.ordered;
100103
}
101104

src/utils/query.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export function firestoreRef(firebase, dispatch, meta) {
143143
*/
144144
function whereToStr(where) {
145145
return isString(where[0])
146-
? `where::${where.join('')}`
146+
? `where=${where.join(':')}`
147147
: where.map(whereToStr);
148148
}
149149

@@ -160,7 +160,7 @@ export function getQueryName(meta) {
160160
if (isString(meta)) {
161161
return meta;
162162
}
163-
const { collection, doc, subcollections, where } = meta;
163+
const { collection, doc, subcollections, where, limit } = meta;
164164
if (!collection) {
165165
throw new Error('Collection is required to build query name');
166166
}
@@ -178,7 +178,11 @@ export function getQueryName(meta) {
178178
if (!isArray(where)) {
179179
throw new Error('where parameter must be an array.');
180180
}
181-
return basePath.concat(`?${whereToStr(where)}`);
181+
basePath = basePath.concat(`?${whereToStr(where)}`);
182+
}
183+
if (typeof limit !== 'undefined') {
184+
const limitStr = `limit=${limit}`;
185+
basePath = basePath.concat(`${where ? '&' : '?'}${limitStr}`);
182186
}
183187
return basePath;
184188
}

src/utils/reducers.js

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ export function pathFromMeta(meta) {
8080
if (storeAs) {
8181
return doc ? `${storeAs}.${doc}` : storeAs;
8282
}
83+
if (meta.path) {
84+
return meta.path.split('/');
85+
}
8386
if (!collection) {
8487
throw new Error('Collection is required to construct reducer path.');
8588
}

test/unit/actions/firestore.spec.js

+24-4
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,20 @@ describe('firestoreActions', () => {
227227
func({
228228
docChanges: [
229229
{
230-
doc: { id: '123ABC', data: () => ({ some: 'value' }) },
230+
doc: {
231+
id: '123ABC',
232+
data: () => ({ some: 'value' }),
233+
ref: {
234+
path: 'test/1/test2/test3',
235+
},
236+
},
231237
type: 'modified',
232238
},
233239
],
234240
size: 2,
235-
doc: { id: '123ABC' },
241+
doc: {
242+
id: '123ABC',
243+
},
236244
});
237245
func2(sinon.spy());
238246
});
@@ -261,11 +269,23 @@ describe('firestoreActions', () => {
261269
func({
262270
docChanges: [
263271
{
264-
doc: { id: '123ABC', data: () => ({ some: 'value' }) },
272+
doc: {
273+
id: '123ABC',
274+
data: () => ({ some: 'value' }),
275+
ref: {
276+
path: 'test/1/test2/test3',
277+
},
278+
},
265279
type: 'modified',
266280
},
267281
{
268-
doc: { id: '123ABC', data: () => ({ some: 'value' }) },
282+
doc: {
283+
id: '234ABC',
284+
data: () => ({ some: 'value' }),
285+
ref: {
286+
path: 'test/1/test2/test3',
287+
},
288+
},
269289
type: 'modified',
270290
},
271291
],

test/unit/utils/query.spec.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,17 @@ describe('query utils', () => {
8181
it('is appended if valid', () => {
8282
const where1 = 'some';
8383
const where2 = 'other';
84+
const whereOperator = '==';
8485
meta = {
8586
collection: 'test',
8687
doc: 'doc',
8788
where: [where1, '==', where2],
8889
};
8990
result = getQueryName(meta);
9091
expect(result).to.equal(
91-
`${meta.collection}/${meta.doc}?where::${where1}==${where2}`,
92+
`${meta.collection}/${
93+
meta.doc
94+
}?where=${where1}:${whereOperator}:${where2}`,
9295
);
9396
});
9497
});

test/unit/utils/reducers.spec.js

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ describe('reducer utils', () => {
7171
pathFromMeta({ storeAs: 'testing' });
7272
});
7373

74+
it('uses path as path if provided', () => {
75+
expect(pathFromMeta({ path: 'testing' })).to.have.property(0, 'testing');
76+
});
77+
7478
describe('updateItemInArray', () => {
7579
it('is exported', () => {
7680
expect(updateItemInArray).to.be.a('function');

0 commit comments

Comments
 (0)