react: Modifying a dictionary inside of a list - reactjs

I have a state object like
this.state = {
newPerson: '',
people: [{name:'Eric', update: false} , {name:'Rick', update:false}, {name:'Yoni', update:false}]
};
I want to map over the list and be able to modify N object (ie - set status to be true).
I was thinking that I could map over the list of dictionaries by checking to see if the name matches N object's name, then "pop out" / delete the dictionary, modify it and then re-add it.
Is there a better way to do this? Especially following react's "functional" programming style by not modifying a object in space.

You can just map over your people list and modify (merge) only the one that matches the requirement (eg name in your example - it won't affect the original array). But the best way would be indexing your objects in collection and then using map function - you can have duplicated names at some point.
I know it's redux docs, but can help you with your problem - https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns

Related

Can I access state values from children components in an array?

I'm very new to React, in the process of learning it for a school project. I've tried searching for this answer thinking it'd be a fairly simple solution, but I'm having trouble finding a result that matches my scenario.
Essentially I'm looking to have an array of a specific component (e.g. Child), each holding a value in their state (e.g. { value: 2 } ). I'm looking to iterate through the array, accessing each component's state.value, and calculate a total from it.
My initial thought was to hold the array in the parent's state, and then iterate through the array doing something like this:
this.state.children.map(child => (
child.state.value
))
However, the result is coming back as 'value' being undefined, leading me to believe I can't access another component's state this way.
I also looked into using refs, as described in the following article:
https://www.geeksforgeeks.org/how-to-access-childs-state-in-react/
However, it seems as though that only lets me create a reference to a single child, meaning I would need a new reference for every child component in the array.
Any advice or sample code of what I could do (the more basic the better) would be greatly appreciated!

ReactJS - Is it possible to render this dictionary (via map) when the keys can change?

Question Is it possible to render a dictionary with a key (which isn't known until an algorithm is run) with a value that is an array, itself with a dictionary with unknown key-value pairs until an algorithm is run?
Detailed information
I have this dictionary:
var currentWorkers = = {EmployeesAtRestaurant :
[{"James" : "Manager"},
{"Jessica" : "Waiter"},
{"Bob" : "Waiter"},
{"Ben" : "Chef"}],
EmployeesAtOffice :
[{"Rebecca" : "Manager"},
{"Nicole" : "Part-time Employee"},
{"Robert" : "Full-time Employee"},
{"Eric" : "Full-time Employee"}],
EmployeesAtZoo :
[{"Robert" : "Manager"},
{"Naomi" : "Part-time Employee"},
{"Jennifer" : "Full-time Employee"},
{"Ken" : "Full-time Employee"}]}
And I want to render it on a page as below (mock up). It is to display employees of an organisation:
What I've tried
I've read some previous answers on Stack (Push component to array of components - ReactJS) of how to attempt this, but their dictionaries use a simple key and value pair, and since my key is not known (i.e I can't do dictionary.Organisation for example) I'm not able to do the above.
I've tried to remodel the dictionary into a model similar to the above, but then I lose a lot of the information above.
Frankly, I'm beginning to suspect my best option is to just remodel the dictionary at this point, if the above is too difficult to attempt.
To make sure I'm understanding your question: Are you talking about the special prop called key[1] that React uses for rendering?
If that's the case, the important thing is that each key is unique, but it doesn't necessarily have to be the same key that your algorithms are calculating.
If you don't have access to the results of your algorithm yet, but you still want to render the strings like in your screenshots, you'll need a different unique key to use while mapping.
The map function on Arrays sends the element as the first function parameter, and the element's index as the second parameter[2]. Lots of places will warn you that index keys aren't the best. As far as I know, this is because if the order of the Array shifts then you lose the optimization that React is trying to provide you.
If index is the only unique data you've got, however, it's reasonable to consider using it. This is especially true if the data is coming from a static source, because you know that the order of the data isn't going to shift out from under you.
Let me know if I've misunderstood your question.
https://reactjs.org/docs/lists-and-keys.html#keys
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

FireStore and maps/arrays, document-list to array in Kotlin

I've finally started to understand a lot of info regarding FireStore, but I'm wondering if I can get some assistance.
If I had a setup similar to or like this:
          races
                Android
                      name: Android
                      size: medium
                       stats          <---- this is the map
                                str: 10
                                sex: 12.... (more values)
How would I parse this? I am looking to make specific TextViews apply values found in the database so that I can simply update the database and my app will populate those values so that hard coding and code updating won't be nearly as troublesome in the future.
I currently use something like this:
val androidRef = db.collection("races").document("Android")
androidRef.get().addOnSuccessListener { document ->
if (document != null) {
oneOfTheTextViews.text = document.getString("str")
} else {
}
The issue is currently I can only seem to access from collection (races) / document (android) / then a single field (I have "str" set as a single field, not part of a map or array)
What would the best practice be to do this? Should I not nest them at all? And if I can reference said nesting/mapping/array, what functions need to be called? (To be clear, I am not asking only whether or not it is possible - the reference guides and documents allude to such - but what property/class/method/etc needs to be called in order to access only one of those values or point to one of those values?).
Second question: Is there a way to get a list of document names? If I have several races, and simply want to make a spinner or recycler view based on document names as part of a collection, can I read that to the app?
What would the best practice be to do this?
If you want to get the value of your str property which is nested within your stats map, please change the following line of code:
oneOfTheTextViews.text = document.getString("str")
to
oneOfTheTextViews.text = document.getString("stats.str")
If your str property is a number and not a String, then instead of the above line of code please use this one:
oneOfTheTextViews.text = document.getLong("stats.str")
Should I not nest them at all?
No, you can nest as many properties as you want within a Map.
Is there a way to get a list of document names?
Yes, simply iterate the collection and get the document ids using getId() function.

How do deal with nested Arrays/objects in BehaviorSubjects, Observables?

I generally have problems using rxjs with nested Objects or Arrays.
My current use-case is this:
{a: [
{b: 0, c:[{d:1}]},
{b: 1, e:[{f: 'someString'}]}
]
Task: Get and set the Observable or value of a,b,c,d,e,f. I also want to be able to subscribe to each property.
I had this Problem in a similar use-case with an Array of BehaviorSubjects:
Efficiently get Observable of an array BehaviorSubjects
I generally have problems to use the basic functionality of nested arrays/objects in rxjs.
The basic functionality I mean includes:
Array:
getting Element by Index
using for of/in on Arrays
setting an Element by Index
push, pop, shift, slice, splice, ...
Object:
getting Value by Property name
going into the nested tree: object.key1.key2.key3[3].key4 ...
setting Value by Property name
assign
for of/in loops
Generally:
Destructuring: e.g.: let [variable1, variable2] = someObject;
Maybe other stuff I forgot.
I dont know if and which functions are possible for which rxjs Objects and which make sense (for example you should be able to set values in an Observable directly). But coming from a background without rxjs, I have trouble to manage my rxjs Objects properly.
I think reason for this besides my lack of knowledge and understanding is, that
a. The rxjs Objects don't provide the functionality as I'm used to from normal arrays and objects. e.g.:
let variable1 = array[1].property;
//becomes this (see related stack-Question I mentioned earlier)
let variable2 = array.pipe(mergeMap(d=> d[index].pipe(map(d1 => d1[property]));
// -> what happens here? You first need to know what mergeMap,
// map is doing and you have 5 levels of nested inline functions.
b. To implement the those mentioned functionalities I need to go over the .pipe() function and use some function like mergeMap, map, pluck, ... Functions that aren't directly indicating that you can get the Observable of let's say 'e' in my example. Making something like object.a[1].e wierd to implement (at least I don't know how to do that yet)
EDIT:
I also want to note, that I still love the idea of rxjs which works well in angular. I just have problems using it to it's full extend, as I'm a bit new to angular and consequently rxjs.
I thin RX is mainly focus on dealing with async operations. Mutation of array and object we can perfectly use the methods comes natively with javascript if theres no existing operators. or you can create your own operator for mutation/iteration etc.
Will try to answer some of your question on array/objects mutation, they are actually very straight forward.
Array:
getting Element by Index
map(arr=>arr[index])
using for of/in on Arrays
map(arr=>arry.map(item=>....))
setting an Element by Index
tap(arr=>arr[index]=somevalue)
Object:
getting Value by Property name
pluck('name')
going into the nested tree: object.key1.key2.key3[3].key4 ...
pluck('key1','key2')
setting Value by Property name
map(obj=>({a:value,obj...}))
assign
lets say your really want some pick array index method as rxjs operator you can create something like, same as for..in operations.
const pluckIndex=(index)=>source=>source.pipe(map(arr=>arr[index]))
const source = of([2,3])
source.pipe(pluckIndex(1)).subscribe(x => console.log(x));

How do I add more meaningful names to ng-model bindings?

The code I am playing around with can be found here.
As of now, in all of my text fields, ng-model has only one name, fieldData. When I take the created javascript object and make it into a JSON object, I get the following:
[{"pHolder":"ID goes here","fieldData":"123"},{"pHolder":"Description goes here","fieldData":"456"},{"pHolder":"Drop Dead Date goes here","fieldData":"789"}]
Since each field has a different meaning, I would like that to be reflected in the bound name.
So instead of an array with three objects that each have the string called fieldData, I would like an array of three objects where foo bar and baz are substituted in each place where there is now fieldData.
How do I do that?
Javascript Array objects are quite flexible, as any other aspect of it, and you can use that to your advantage :) ngRepeat iterates through any array, be it ordered or associative (which are basically the same). So, if you change your array to:
$scope.entryFields = {
id: {pHolder:'ID goes here',fieldData:""},
description: {pHolder:'Description goes here',fieldData:""},
date: {pHolder:'Drop Dead Date goes here',fieldData:""}
};
The ng-repeat element will still work (you may want to reorder it, as it orders alphabetically by key name, by default) without any changes, but you can adress the fields by name (dot notation). See the updated fiddle here.

Resources