How do you perform deep array updates with mobx? - javascript

I have one observable array in my store that is deeply nested. Lets called the property people (which contains elements of class Person). Now the Person class has a property products which is an array of Product, a class which also has nesting through ShippingInformation and so on. When the app is loaded I get the people array with all nested data. Now upon any data update I receive the updated peoples array again from the server. A lot of the times the elements in the people array are the same, the only change being some ShippingInformation.
Now how should I update the existing observable array people? I do not want to reassign it because often times the direct Person elements are the same. It is only some nested information on one Person that has changed. Is there a way that I can sync the two arrays without changing the ref on the array with a reassign so that I avoid major rerenders in react? Can mobx help me here or are there any other lib I can use to help me update without triggering unnecessary rerenders? If not, are these rerenders that bad, performance wise, I guess react must go through the diffing process at least

Related

Best practices to concat async data in React

Currently, I'm making three API calls in 3 separate epics and updating specific states with the 3 returned promise objects. After states are updated via redux, I'm trying to concat all 3 arrays together in a certain order and then display them on the page. I believe there's a problem since these are async and data is coming back at different times. My component that renders the data is looking for this combined array but the array is not fully populated before the render happens.
Sometimes the array will have a couple objects and sometimes it' will have 50 when Im searching the same thing. I know what the exact amount of data objects is suppose to be returned. Where should the best place be to concat all the data from when I submit the search query to when the data gets rendered on the page? Right now I'm performing the concat in componentDidMount of the component that is suppose to render the data, but it isn't reliable.
Tried to concat the 3 arrays into one in a separate function and then passing it into the reducer.
Also tried concatting inside componentDidMount and then passing it into the reducer.
Can't show code.
The simplest thing you could probably do is to have a single api endpoint that returns you the three arrays already joined together - basically pushing this logic to the server. But if that is not feasible...
I think the reason your code is not working the way you want is that componentDidMount will only fire once - when the components initially mounts. As the different calls take different times to come back, you'll only see whatever was loaded when componentDidMount happened to fire.
Some possible ideas:
One approach you could use is to pass the three arrays into your component as props, and concat them in the render method. As each one is populated, your component will re-render itself and keep itself up-to-date.
Personally I'd consider the concat call to be "data logic" (not "view logic") and thus keeping it out of your react components could be a good idea. You could consider using something like Reselect to move the logic more into your redux code.
By default both of these approaches will cause your react component to rerender as each of the ajax calls returns. If this is a problem for your data sizes, you could then look into optimisations to make it faster.

Why use setState in React?

If I have a class with a bunch of properties, it seems like a hassle to put the properties that I modify inside (for example) this.state.myProp1 instead of this.myProp1. and then I need to make a copy of whatever property it is before I send it off to setState (because I can't mutate it directly). Like an array of objects for example.
At some point I display some of these properties so that means that I need to hold all my class properties inside this state, and then keep track of what I need to refresh, instead of refreshing the whole thing.
I almost prefer to use this.forceUpdate() instead and have my render() refer to class properties directly. Why does react "make" people use this.state and setState. Is it for performance reasons?
setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses.
So basically setState is there to tell react when to re-render. Also setState behaves asynchronously, and updates the state only when necessary. So if you call setState multiple times immediately it will update only on the last one so as to minimize the number of re-renders and be less taxing on the browser. If there was no setState and react re-rendered every time the data changed, the browser experience would be terrible.
You don't have to use React this.state and setState if you don't want to. You can always use redux or mobx to manage the state.
Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made.
And yeah, that's why you've to make a copy of whatever property it is before I send it off to setState
IMHO, component state is an elegant concept for some special case. for example when you want to monitor the content change of a text input on live, that is, not after hit save or submit button. under such situation, a component state would be ideal place to store the temporary input and you will not get overhead to use redux action to respond on the every incomplete input. it is just like a buffer to provide performance improvement.
1. Reasons behind setState
The main reason for having to use setState is its asynchronous execution, from the react docs:
React intentionally “waits” until all components call setState() in their event handlers before starting to re-render. This boosts performance by avoiding unnecessary re-renders.
If the state object was updated synchronously it would cause consistency issues, since props are not updated until the parent component is re-rendered, so, mutating this.state directly would lead to inconsistency between props and state.
For further reference, you can check this this Github thread.
2. Reasons behind this.state
The main advantage of the state object is its immutability which couldn't be accomplished with component properties, also there is the separation of responsibility between props and state, which is way easier to handle and update individually.
Why does react "make" people use this.state and setState. Is it for performance reasons?
That's a good question - the existing answer from J. Pichardo is quite correct but I wanted to address the why in a little more depth - as opposed to what or how.
Really a better question is - why does React exist? According to this article
React’s one-way data flow makes things much simpler, more predictable, and less bug-prone. One way data flow greatly simplifies your thinking about state because no view can ever mutate the state directly. Views can only send actions up to the global state store.
Really theres a whole bunch of reasons why React has it's place as a useful UI library. But in regards to your question - uni-directional data flow - this is the main reason.
relational UIs get complex. When an app has to consume, display and update even just a modest amount of relational data and have that information displayed across multiple elements, things can get messy fast.
Using state and props the way that React does allows one to differentiate and guarantee whether a piece of the UI will just receive data to display or whether it might change it too.
If you store that data just in a random key you have no real way of knowing whether the value is changed and what changed it. By separating out your state from your component in this way, it decouples the data from the element and makes it much easier to share data between elements and also change that data in different ways.
according to this article on coupled object interfaces a tightly coupled entity is bad because:
A tightly Coupled Object is an object that needs to know about other objects and are usually highly dependent on each other's interfaces. When we change one object in a tightly coupled application often it requires changes to a number of other objects. There is no problem in a small application we can easily identify the change. But in the case of a large applications these inter-dependencies are not always known by every consumer or other developers or there is many chance of future changes.
This very much is applicable in UI development also. In my opinion this is why not setting state is going to cause you some pain later on.

Accessing and replacing values in a Knockout Observable Array

I've been having difficulty understanding how Knockout Observable Arrays work, more specifically replacing certain vales within them. I keep thinking I've got it right until further down the line when something else doesn't work correctly.
Due to the complexity of my viewmodel (Observable Arrays of Observable Arrays of Observables with subscriptions to update their respective arrays) I won't post the full extent of my actual issue, especially as there is clearly a fundamental misunderstanding here.
I've essentially got it narrowed down to 2 possibilities, examples below, where; groups = KO Array of observable objects/arrays and rightTargetPropertyName = KO array of obs strings
filter().groups()[0].rightTargetPropertyName([ko.observable("placeholder")])[0];
The above works but I feel like it will replace the whole array with a single value as the UI grows
filter().groups()[0].rightTargetPropertyName()[0]("placeholder");
This one above seems like it should be the correct way to change a single observable value in an observable array but the subscriptions/computed values aren't triggered when this code is run.
So in summary, which is the correct way to modify observable values in observable arrays? If the second method is correct (as I suspect) I can debug further.
Thanks in advance

Angular HTTP observables behave differently compared to regular observables?

While I was messing with routing in Angular, I tried using an in memory database to fetch the heroes.
The original StackBlitz is https://stackblitz.com/angular/yoerxnmrbod
If you go to the heroes tab, click on a hero, and change his name, the change is reflected in the list.
I changed how the data is backed to be the angular in memory database.
https://stackblitz.com/edit/angular-ke7pxn-vxp9hi?file=src/app/app.module.ts
If you follow the same workflow as the above, the name change in the details component isn't reflected in the list. What am I missing to get the same functionality?
It seems that the reason is when you set HEROES as const in hero.service and then pass a separate hero and change his name, the name is changed in your HEROES array element (because it's an array of objects, and even if it is const, it's elements and their properties can be changed). And in the second realization, you always get a new instance of heroes array. If you want to save some changes to it, you should store it in your service and use like a simple array (without async pipe) and not receive it from your mock-backend each time.

Can / should I call firebaseRef.set passing an array?

The question title says it all. Here are a couple related pages from the Firebase docs:
writing data
managing lists
Is there a better way to update all the items in an "array" on Firebase?
Note that using .push on a ref in firebase does not append to an array but rather an array-like object with non-ordinal keys that look like -JH1w9H0qPJIFu_OF_JO. If you want to work with actual JavaScript arrays, you need to treat them as a unit. That is, any time you update a property that contains an array you have to set the entire array -- you can't use Firebase to update individual components of the array.
If you need ordered data, use priorities.
That being said, it is safe to write arrays ([]) as properties in Firebase. If you have a list and you need to update each property of the list, you cycle through the snapshot (once you've retrieved it from the ref using .value or the like) using .forEach. You can then us .update on each individual child.

Categories

Resources