Can I get data from an NgRx service without updating cache? - ngrx

I have my service and need to get data using getWithQuery, but I don't need NgRx store to be updated. I just need to get this data and use them in subscribe method.
I've tried different EntityActionOptions.mergeStrategy but cache is still updated.
Any ideas?
Thanks!

This isn't possible AFAIK #ngrx/data is bound to the store.
If you just need the data, you can invoke the service directly.

The ngrx store purpose is to be responsible for the app state. It means if you want to fetch something you dispatch an action that updates the store and then you select this data from the store.
If you want to fetch data directly skipping the store and select parts - it means you follow against ngrx purpose and perhaps you don't ngrx at all.
If you want to ngrx then consider writing you app in the way that it always puts data into the store if something is updated / fetched and to display the data it's always selected from the store.

Related

When writing to Firestore, how can I know that all triggered have finsihed?

Background: I am using Firestore as the main database for my (web) application. I also pre-render the data stored in there, which basically means that I collect all data needed for specific requests so I can later fetch them in a single read access, and I store that pre-rendered data in a separate Firestore collection.
When a user changes some data, I want to know when this background rendering is finished, so I can then show updated data. Until rendering is finished, I want to show a loading indicator ("spinner") so the user knows that what he is currently looking at is outdated data.
Until now, I planned to have the application write the changed data into the database and use a cloud funtion to propagate the changed data to the collection of pre-rendered data. This poses a problem because the writing application only knows when the original write access is finished, but not when the re-rendering is finished, so it doesn't know when to update its views. I can hook into the table of rendered views to get an update when the rendering finished, but that callback won't be notified if nothing visibly changes, so I still do not know when to remove the spinner.
My second idea was to have the renderer function publish to a pubsub topic, but this fails because if the user's requests happens to leave the original data unchanged, the onUpdate/renderer is not called, so nothing gets published on the pubsub and again the client does not know when to remove the spinner.
In both cases, I could theoretically first fetch the data and look if something changed, but I feel that this too easily introduces subtle bugs.
My final idea was to disallow direct writes to the database and have all write actions be performed through cloud functions instead, that is, more like a classical backend. These functions could then run the renderer and only send a response (or publish to a pubsub) when the renderer is finished. But this has two new problems: First, these functions have full write access to the whole database and I'm back to checking the user's permissions manually like in a classical backend, not being able to make use of Firestore's rules for permissions. Second, in this approach the renderer won't get before/after snapshots automatically like it would get for onUpdate, so I'm back to fetching each record before updating so the renderer knows what changed and won't re-render huge parts of the database that were not actually affected at all.
Ideally, what (I think) I need is either
(1) a way to know when a write access to the database has finished including the onUpdate trigger, or
(2) a way to have onUpdate called for a write access that didn't actually change the database (all updated fields were updated to the values they already contained).
Is there any way to do this in Firestore / cloud functions?
You could increment a counter in the rendered documents, in such a way a field always changes even if there is no change for the "meaningful" fields
For that, the best is to use FieldValue.increment.

When is it better to call an API to update a component or just change its state by it's reducer?

I have two components,in the first one i have an array of objects I get by calling the API (in y useEffect, only if the array in the store is empty, to avoid unnecessary calls). In the second one, the same array but with buttons to call the API and DELETE or POST a new object to that array in the server. My question is, is it better to create 2 actions in my second component's actions, for making the api updates, and then filter or push that object in my first component's reducer? Or just make the first component to always call the API and update itself?
I don't know if it's better to update the store as mutch as u can without relying on an API call or just an API call for updating will be more smooth.
I would recommend you to update the first component always with API call. If so, you can be sure that data has updated properly in DB via service call and you will always get updated data from DB.
Doing more and more updates at UI and keeping them in store will leave you with dirty data after a while.
It makes your app buggy (You should keep reverting/clearing the data in store in failure scenarios. Which we might miss at some point of time) too.

Does Redux Use Persistent Data Structure?

What type of data structure does redux use for making the data persist in Angular and React.js? I am assuming it uses persistent data structures.
Redux is an architecture for managing your state. It doesn't use any data structure. It keeps the data structure which you provide to it, i.e., state. If you want to keep an eye in your store and want to go back to the actions fired then you'll have to maintain that in your state and handle that yourself. Some modules like redux state history provide that for you. You might as well want to look at implementing undo history with redux in which you'll find that nothing is persistent with redux but you'll have to make your app persistent by storing history. Redux devtools will give you the freedom of changing your state dynamically in the browser by going back in the history of actions fired.
Redux doesn't actually use any data structures itself. The "current state" value is whatever you return from your root reducer function. That could be a simple counter value, a plain JS array or object, an Immutable.js Map or List, or something else.
I'm not sure I understand fully your question but
"In computing, a persistent data structure is a data structure that always preserves the previous version of itself when it is modified"
As far as I know redux is just a pattern and there is no persistant data structures associated with, unless you create and bind something yourself (like mongo event sourcing for example).

Responsibility of store in flux

In flux I'm wondering, is it okay to
make async operation
change multiple values (by different keys) in state
trigger actions
in a single store? If I need to update 2 keys of store, should I create another store to separate concerns and make store responsible for a single first level property in state?
E.g. in Redux reducer is responsible for a single first level key on resulted object, asaik
Make async operations:
Typically it is better to keep your stores synchronous... they should be dumb and just receive data. Makes everything easier and testable! The action creator should dispatch the appropriate action once it has resolved.
Change multiple values (by different keys) in state:
This isn't that bad, but as you eluded too, perhaps you need to rethink how your app state is structured. It depends on the action though... hard to say without knowing the context.
Trigger actions:
Your views are responsible for triggering actions... So stores should not trigger actions!
Some links:
Async requests with React.js and Flux, revisited.
Using a Redux store in your React.js application

How To Use Flux Stores

Most examples of Flux use a todo or chat example. In all those examples, the data set you are storing is somewhat small and and be kept locally so not exactly sure if my planned use of stores falls in line with the flux "way".
The way I intend to use stores are somewhat like ORM repositories. A way to access data in multiple ways and persist data to the data service, whatever that might be.
Lets say I am building a project management system. I would probably have methods like these for data retrieval:
getIssueById
getIssuesByProject
getIssuesByAssignedUser
getIssueComments
getIssueCommentById
etc...
I would also have methods like this for persisting data to the data service:
addIssue
updateIssue
removeIssue
addIssueComment
etc...
The one main thing I would not do is locally store any issue data (and for that matter most store data that related to a data store). Most of the data is important to have fresh because maybe the issue status has updated since I last retrieved that issue. All my data retrieval method would probably always make an API requests to the the latest data.
Is this against the flux "way"? Are there any issue with going about flux in this way?
I wouldn't get too hung up on the term "store". You need create application state in some way if you want your components to render something. If you need to clear that state every time a different request is made, no problem. Here's how things would flow with getIssueById(), as an example:
component calls store.getIssueById(id)
returns empty object since issue isn't in store's cache
the store calls action.fetchIssue(id)
component renders empty state
server responds with issue data and calls action.receiveIssue(data)
store caches that data and dispatches a change event
component responds to event by calling store.getIssueById(id)
the issue data is returned
component renders data
Persisting changes would be similar, with only the most recent server response being held in the store.
user interaction in component triggers action.updateIssue(modifiedIssue)
store handles action, sending changes to server
server responds with updated issue and calls action.receiveIssue(data)
...and so on with the last 4 steps from above.
As you can see, it's not really about modeling your data, just controlling how it comes and goes.

Resources