Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(actions): add MULTIPLE_DOCUMENTS_ADDED event to group doc updates #319

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const actionTypes = {
DOCUMENT_ADDED: `${actionsPrefix}/DOCUMENT_ADDED`,
DOCUMENT_MODIFIED: `${actionsPrefix}/DOCUMENT_MODIFIED`,
DOCUMENT_REMOVED: `${actionsPrefix}/DOCUMENT_REMOVED`,
MULTIPLE_DOCUMENTS_ADDED: `${actionsPrefix}/MULTIPLE_DOCUMENTS_ADDED`,
TRANSACTION_START: `${actionsPrefix}/TRANSACTION_START`,
TRANSACTION_SUCCESS: `${actionsPrefix}/TRANSACTION_SUCCESS`,
TRANSACTION_FAILURE: `${actionsPrefix}/TRANSACTION_FAILURE`,
Expand Down
1 change: 1 addition & 0 deletions src/reducers/crossSliceReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function crossSliceReducer(state = {}, action) {
case actionTypes.DOCUMENT_MODIFIED:
case actionTypes.DOCUMENT_ADDED:
case actionTypes.DOCUMENT_REMOVED:
case actionTypes.MULTIPLE_DOCUMENTS_ADDED:
case actionTypes.LISTENER_RESPONSE:
case actionTypes.UNSET_LISTENER:
// Take all of the query values and plop them into composite, replacing the existing data entirely
Expand Down
8 changes: 8 additions & 0 deletions src/reducers/dataReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
DOCUMENT_ADDED,
DOCUMENT_MODIFIED,
DOCUMENT_REMOVED,
MULTIPLE_DOCUMENTS_ADDED,
} = actionTypes;

/**
Expand Down Expand Up @@ -74,6 +75,13 @@ export default function dataReducer(state = {}, action) {
action.payload.data,
state,
);
case MULTIPLE_DOCUMENTS_ADDED:
return action.payload.reduce((futureState, change) => setWith(
Object,
pathFromMeta(change.meta),
change.payload.data,
futureState
), state)
case DOCUMENT_REMOVED:
case DELETE_SUCCESS:
const removePath = pathFromMeta(action.meta);
Expand Down
14 changes: 14 additions & 0 deletions src/reducers/orderedReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {

const {
DOCUMENT_ADDED,
MULTIPLE_DOCUMENTS_ADDED,
GET_SUCCESS,
LISTENER_RESPONSE,
CLEAR_DATA,
Expand Down Expand Up @@ -111,6 +112,18 @@ function addDoc(array = [], action) {
return modifyDoc(array, action);
}

/**
* Case reducer for adding multiple documents to a collection or subcollection.
* @param {Array} [array=[]] - Redux state of current collection
* @param {object} action - The action that was dispatched
* @returns {Array} State with document modified
*/
function addMultipleDocs(array=[], action) {
const { payload } = action;

return payload.reduce((futureState, changeAction) => addDoc(futureState, changeAction), array)
}

/**
* Case reducer for adding a document to a collection.
* @param {Array} array - Redux state of current collection
Expand Down Expand Up @@ -240,6 +253,7 @@ const actionHandlers = {
[DOCUMENT_ADDED]: addDoc,
[DOCUMENT_MODIFIED]: modifyDoc,
[DOCUMENT_REMOVED]: removeDoc,
[MULTIPLE_DOCUMENTS_ADDED]: addMultipleDocs,
[DELETE_SUCCESS]: removeDoc,
[LISTENER_RESPONSE]: writeCollection,
[GET_SUCCESS]: writeCollection,
Expand Down
5 changes: 5 additions & 0 deletions src/reducers/queriesReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export default function queriesReducer(state = {}, action) {
case actionTypes.DOCUMENT_MODIFIED:
set(draft, [key, 'data', action.meta.doc], action.payload.data);
return draft;
case actionTypes.MULTIPLE_DOCUMENTS_ADDED:
action.payload.forEach(changeAction => {
set(draft, [key, 'data', changeAction.meta.doc], changeAction.payload.data);
})
return draft;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not postive, but I think we should be returning a copy here

Copy link
Author

@mike-lvov mike-lvov May 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prescottprue I was just following the way it's done in other cases. For ex. a few lines above, you modify draft directly. Correct me, if I'm wrong though

image

case actionTypes.DOCUMENT_REMOVED:
case actionTypes.DELETE_SUCCESS:
unset(draft, [key, 'data', action.meta.doc]);
Expand Down
48 changes: 45 additions & 3 deletions src/utils/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
get,
set,
cloneDeep,
partition
} from 'lodash';
import { actionTypes } from '../constants';

Expand Down Expand Up @@ -735,6 +736,43 @@ function docChangeEvent(change, originalMeta = {}) {
};
}

/**
* Action creator for multiple document additions event. Used to create action objects
* to be passed to dispatch.
* @param {object} additions - Array of document addition objects from Firebase callback
* @param {object} [originalMeta={}] - Original meta data of action
* @returns {object} Resolves with docs change action object
*/
function docMultipleAdditionsEvent(additionObjects, originalMeta= {}) {
const additionsToMake = additionObjects.map(change => {
const meta = { ...cloneDeep(originalMeta),
path: change.doc.ref.path
};

if (originalMeta.subcollections && !originalMeta.storeAs) {
meta.subcollections[0] = { ...meta.subcollections[0],
doc: change.doc.id
};
} else {
meta.doc = change.doc.id;
}

return ({
meta,
payload: {
data: change.doc.data(),
ordered: { oldIndex: change.oldIndex, newIndex: change.newIndex },
},
})
})

return {
meta: originalMeta,
type: actionTypes.MULTIPLE_DOCUMENTS_ADDED,
payload: additionsToMake
};
}

/**
* Dispatch action(s) response from listener response.
* @private
Expand All @@ -761,9 +799,13 @@ export function dispatchListenerResponse({
: docData.docChanges;
// Dispatch different actions for doc changes (only update doc(s) by key)
if (docChanges && docChanges.length < docData.size) {
// Loop to dispatch for each change if there are multiple
// TODO: Option for dispatching multiple changes in single action
docChanges.forEach(change => {
// Divide docChanges by types
const [docAdditions, otherDocChanges] = partition(docChanges, (change) => changeTypeToEventType[change.type] === actionTypes.DOCUMENT_ADDED)

dispatch(docMultipleAdditionsEvent(docAdditions, meta))

// Handle all other doc changes
otherDocChanges.forEach(change => {
dispatch(docChangeEvent(change, meta));
});
} else {
Expand Down