Can two arrays be compared in componentWillReceiveProps react method? - reactjs

I was searching for some react projects examples and i have found some here
https://reactjs.org/community/examples.html
One of them is a shopping cart project, i checked the code and i have found something that i could not understand, comparing two arrays in componentWillReceiveProps method.
I know that comparing two arrays always will return false and this was the source of confusion, here
https://github.com/jeffersonRibeiro/react-shopping-cart/blob/master/src/components/Shelf/index.js
My problem is in this part
if (nextFilters !== this.props.filters) {
this.handleFetchProducts(nextFilters, undefined);
}
Since filters is an array as shown in propTypes.
Everything works well, and this what made me ask the question.
So what is the deal here, is componentWillReceiveProps is a special method so it can make at least a shallow compare between two arrays or what exactly is happening here???

This might duplicate answers so you might find this useful:
check if two arrays contain identical objects - react componentDidUpdate
For your information using getSnapshotBeforeUpdate(prevProps, prevState) is now preferred over componentWillReceiveProps see the react docs , https://reactjs.org/docs/react-component.html#getsnapshotbeforeupdate

Related

Splice removing incorrect index react

I know this question has been asked time and time again but I seem to be running into the same issue as others. I am attempting to add/remove textareas, but when using splice, I seem only to be removing the last element added regardless of what I try to delete.
EDIT: Solution was to ensure the entire state is controlled. This means textareas should have values in the state that are updated when text is entered/deleted.
I've tried your example and it works although I agree with the other answers that this is not a correct way of working.
The problem though is, I assume, in a part of your code that you did not include. The part where you use addText. I think that is called after delete again.
Suggestions:
consider other namings. addText as a function AND a state is confusing
take the array from the state, splice it and put it back in the state
UPDATED MY CODE so it does not mutate original state
removeText(index) {
console.log(index);
const addTextArray = [...this.state.addText];
addTextArray.splice(index, 1);
this.setState({...this.state, addText: [...addTextArray]});
}

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!

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

Is it safe to memoize JSX elements to pass them later in props to owned components?

Consider an example:
const someElement = <CustomElement value="some" />;
function Foo({ style }) {
return <Bar style={style}>{someElement}</Bar>;
}
Are there any pitfalls if I want to keep passing the same instance of React element as props to children? How normal and acceptable is this specific case for React's reconciliation?
I suspect that your approach is sound. Then again, I'm not sure this will solve your problem; it still has to calculate someElement. I would consider using truly static data (e.g. literal HTML) and I believe React has specific facilities for that (dangerouslySetInnerHTML?). Also, note that when Bar updates it still has to do a DOM compare all the way down the tree. It would not seem that it could know there's something special about someElement that would obviate the need to compare that part of the DOM tree. I think you'd need to at least give the outer tag of your literal a key but this key needn't change unless you repeat the stuff as siblings. This approach seems fraught even though it may be technically sound.
Another approach that might work is to make it a traditional component but override the method that tells it whether it needs to update. Obviously, it never needs to update but it would still incur the cost of the initial calculation of the DOM. I believe your suggestion still incurs that cost, as well. Maybe a component that does nothing but dangerouslySetInnerHTML and refuses all updates could do the trick; zero calculation.

why splice not working correctly in react?

I am trying to delete row from my list using delete button .I do like this
if (state.indexOf(action.payload) > -1) {
console.log('iff----')
state.splice(state.indexOf(action.payload), 1);
}
console.log(state)
return state
but it is not deleting the row .here is my code
https://plnkr.co/edit/bpSGPLLoDZcofV4DYxPe?p=preview
Actually using add button I am generating the list of item and there is delete button I am trying to delete item from list using delete button
could you please tell me why it is not working ?
Avoid using Array#splice when working with state in React or Redux. This mutates your state, which you never want to do. Instead, favour immutable methods like Array#slice. e.g.
const index = state.indexOf(action.payload);
if (index === -1) {
return state;
}
return [...state.slice(0, index), ...state.slice(index + 1)];
The flaw of this approach is that in JavaScript, objects and arrays are reference types, so when we get an array, we actually get a pointer to the original array's object managed by react. If we then splice it, we already mutate the original data and whilst it does work without throwing an error, this is not really how we should do it, this can lead to unpredictable apps and is definitely a bad practice. A good practice is to create a copy of the array before manipulating it and a simple way of doing this is by calling the slice method. Slice without arguments simply copies the full array and returns a new one which is then stored. And we can now safely edit this new one and then update to react state with our new array. let me give you and example:
We have an array like this const arr=[1,2,3,4,5]. This is original array.
As I told you before, we can do that like this:
const newVar=arr.slice();
newVar.splice(Index,1);
console.log(newVar);
Or
An alternative to this approach would be to use it a ES6 feature, it is the Spread Operator
Our prior code can be something like this:
const newVar=[...arr]
newVar.splice(Index,1);
console.log(newVar);
That's it. Good luck

Resources