Learning more about Redux Sagas and the Reducer pattern and want to ask for how to abstract my workflow in a sensible way.
I have a backend Firestore collections of "tags" documents like this very simple.
A Tag is a json object like {"name": "Bmw"}.
When a Tag is changed, modified or deleted I use the Saga Channel to listen on changes like this.
Here's the code simple setup:
function* tagsListenerSaga() {
const firebase = yield getContext('firebase');
const ref = firebase.db.collection(FIRESTORE.GLOBAL_TAGS).orderBy(FIRESTORE.NAME);
const channel = yield call(metaEventListener, ref);
try {
while (true) {
const querySnapshot = yield take(channel);
const addedTags = [];
const modifiedTags = [];
const deletedTags = [];
querySnapshot.docChanges().forEach(doc => {
if (doc.type === 'added') {
console.log('added : ', doc.doc.data());
addedTags.push({
...doc.doc.data(),
id: doc.doc.id,
});
}
if (doc.type === 'modified') {
console.log('modified : ', doc.doc.data());
modifiedTags.push({
...doc.doc.data(),
id: doc.doc.id,
});
}
if (doc.type === 'removed') {
console.log('removed : ', doc.doc.data());
deletedTags.push({
...doc.doc.data(),
id: doc.doc.id,
});
}
});
if (addedTags.length) {
yield put(setTagsAdded(addedTags));
}
if (modifiedTags.length) {
// yield put(setTagsModified(modifiedTags));
}
if (deletedTags.length) {
// yield put(setTagsDeleted(deletedTags));
}
}
} catch (error) {
console.log(error);
} finally {
if (yield cancelled()) {
console.log('error');
channel.close();
}
}
}
const metaEventListener = ref => {
const channel = eventChannel(emitter => {
const unsubscribe = ref.onSnapshot(doc => {
emitter(doc);
});
return unsubscribe;
});
return channel;
};
export default function* watchTagsMetaRequests() {
yield takeLatest(globalActionTypes.START_LISTEN_TAGS, tagsListenerSaga);
}
As you see in the Saga I respond to Firebase querySnapshot
and calling yield put(setTagsAdded(addedTags));
to the reducer
to save the addedTags
.
In the Saga I have all three:
if (addedTags.length) {
yield put(setTagsAdded(addedTags));
}
if (modifiedTags.length) {
// yield put(setTagsModified(modifiedTags));
}
if (deletedTags.length) {
// yield put(setTagsDeleted(deletedTags));
}
To handle delegate the data toward the reducer
and I must somewhere add this tag
changes to the reducer
state.
Dose it make sense to insted send the querySnapshot
to the reducer
and inside reducer
search through the tags
map and add/delete/update tags
or,
should/could the Saga select
the reducer
state needed to do this and then the Saga do the yield put..
with an updated tags
map. What happens regarding transactions state and atomicy here?
I want to adhere the Single responsibility principle (SRP) in the best way for future best modulations
pros and cons please?