Understanding react function notation - reactjs

Learning react here. Can someone walk me through how to interpret the function below:
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
As far as I understand it, this is the same as calling:
onElementsRemove(setElements(elementsToRemove(els))?
Is that correct? Is there a benefit to the first notation? Perhaps I am biased coming from the python side of the world but the second one feels more compact? Can someone help me undrstand the reasoning? Thanks!

No, those are not the same. Let's start with the inner part, which needs to be the way it is:
setElements((els) => removeElements(elementsToRemove, els))
When setting state in react, there are two options. You can either directly pass in what you want the new state to be, or you can pass in a function. If you pass in a function, then react will look up what the latest value of the state is, and call your function. Then you return what the new state will be.
So the purpose of doing it this way is to find out what the latest value in the state is. There isn't another way to do this.
Next, the outer part, which has more flexibility:
const onElementsRemove = (elementsToRemove) => /* the stuff we looked at earlier */
This is defining a function called onElementsRemove. From the name, i assume that this is going to be called at some arbitrary point of time in the future. So it's just defining the functionality, and later on you can call it, once you know which elements you want to remove. It will then turn around and set the state. For example, you would do:
onElementsRemove([1, 2, 3]); // i don't actually know what will be in the array
Maybe having this outer function is useful, maybe not. If you're having to do this fairly often it could make sense. In other cases, maybe you could directly call setElements, as in:
setElements((els) => removeElements([1, 2, 3], els));

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!

Which param triggered React.useMemo recalculation?

here is my React hooks code:
function calc_c({a,b}){
//some long calculation that is based on a,b
}
function MyComponent(params){
var a=calc_a(params)
var a=calc_b(params)
var c=React.useMemo(()=>calc_c({a,b},[a,b])
}
my question: how to I find out which of the params in [a,b] changed and caused the calls to calc_c
edit: I ended up using a generic version of skyboyer excelent answer:
export function useChanged(name,value){
function print_it(){
console.log('changed',name)
}
React.useMemo(print_it,[value])
}
It depends whether you ask for debugging purposes or you'd like to rely on that in your code(e.g. "if A is changed then return B, otherwise C")
For both cases, there is no simple way to achieve. But work arounds would differ.
Assume you just want to figure out why this is recalculated. Then just put bazillion
useEffect(() => {
console.log("a is changed");
}, [a])
One per each dependency. Yes, boring and repetitive. But the simplest approach is, the less you should actually worry about additionally. Or take a look if useWhatChaged works to you(if there are literally dozen variables in dependency list).
Another thing, if you would like to make check(but why?) in your regular(not in temporary code for debugging purposes I mean). Then you might use usePrevious or write something similar.

How to call a variable within a Redux state?

How do I call a variable, such as device_id, device_name, or group_id within the device state in Redux?
{JSON.stringify(device.deviceData)} works great and displays all the state information within deviceData, but {JSON.stringify(device.deviceData.device_id)} doesn't show any information.
Given the 0 pin, I also tried {JSON.stringify(device.deviceData.0.device_id)} but this resulted in an error. I wouldn't want to work with that solution anyway though since I want this call to be universal instead of assigning a specific number in that call.
My Redux state is screenshotted below
deviceData appears to be an array. So you may access the first item like this: device.deviceData[0].device_id
How could I make that universal, in pseudo-terms: device.deviceData[all indexes].device_id if I wanted to make a list of the device_id's for example?
You can use array.map to create a new array with only the device_ids.
const device_ids = device.deviceData.map((data) => data.device_id);

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));

Programmatically composing a chain

I would like to be able to programmatically compose a chain, for later inclusion in another chain. I know it can't be that hard, but I seem to be missing something.
In theory, I should be able to do something like this:
var c = ??? // the part I can't figure out
List( 1, 2, 3 ).foreach {
c.exec( http("Fetch something").get("..." + _ ) )
}
That is, I expect to be able to create a chain, then populate that chain in a loop, rather than hard-coding the chain in the source code.
My biggest struggle, I think, is knowing what to assign to c. I had assumed that it should be
var c = new ChainBuilder()
but according to the documentation I have to pass it a list of actionBuilders and the next action, implying that it is not possible to build an empty chain and then build on it in a separate statement.
Is there any way to make my .foreach loop work the way I intend it to work?
The answer is
import bootstrap._
and then
var c = bootstrap
But then the loop must be modified, like so:
List( 1, 2, 3 ).foreach( x => {
c = c.exec( ... )
})
The reason has to do with the fact that you have to do what chaining does. When you have
foo()
.bar()
.blip()
The result of the whole expression is the return value from blip and not foo - which is obvious when you think about it - so the variable that we are attaching to has to move as nodes are attached.
I hope someone, somewhere, besides me, finds value in seeing this example.

Resources