Difference between these two functions that handle the state - reactjs

I tried these two functions and I thought they do the same thing, but apparently no.
The first Function:
setEatenFoodList(prevList => {
const newList = [];
for (let i=0 ; i<prevList.length ; i++) {
if (i === index){
const editedFood = prevList[i];
editedFood.removingFade = true;
newList.push(editedFood)
} else {
newList.push(prevList[i])
}
}
return newList;
})
The second Function:
setEatenFoodList(prevList => {
prevList[index].removingFade = true;
return prevList;
})
I don't see the difference ?

The first code creates a new list called "newList" and iterates through the elements of the original list "prevList" and adds them to the new list. If the current index of the loop is equal to the variable "index", it creates a new variable called "editedFood" which is a copy of the element at that index, sets the "removingFade" property of "editedFood" to true and pushes it to the "newList". Finally, it returns the "newList" as the output.
The second code is simpler, it directly modifies the "prevList" by setting the "removingFade" property of the element at index "index" to true. And it returns the original list "prevList" as output.
The main difference between the two codes is that the first one creates a new list, whereas the second one modifies the original list.
More simply: the first function iterates through all the elements of newList and pushes everything inside the newList. The second function pushes everything into the original list (prevList)

Related

update objects in array with useState (reactJS)

Go to the end of this question for the solution that worked for me!
i'm currently making my own chess game and i want to check if a position already occurred 3 times. I keep the current position in a 2d array. This is what i tried:
Initialize the useState:
const [positionList, setPositionList] = useState([])
structure of the state should look like this
[
{
position: //some 2d array,
counter: 1
},
{
position: //another 2d array,
counter: 1
}
]
Compare the positions from the array with the current position
(if the position already existed, set counter one up)
let found = false
for (let i = 0; i < positionList.length; i++) {
if (JSON.stringify(positionList[i].position) === JSON.stringify(position)) {
positionList[i].counter = positionList[i].counter + 1
found = true;
break;
}
}
if the position never occurred before, add it to the array
if (found === false) {
setPositionList([...positionList, {position: position, counter: 1}]);
}
The 2nd and 3rd code block gets executed after every move (after players turn).
But for some reason, if "found" is false, it wont add the new position to the array but replace the last object in the array. And furthermore, when i log the changes made to "positionList" with a useEffect, it gets reset after every move to the default value (basically empty array), even though im not changing the state in any other part of my code.
I log the positionList like this:
useEffect(() => {
console.log(positionList)
}, [positionList])
I just cant figure out my error, hopefully someone can help.
Thanks!
EDIT:
I decided to try another way of counting the positions. I now only have one array which contains every position that occured in the correct order. Then i just loop through the array and count the amount of times the current position is in the array. My code looks like this:
Note: I think its important to note that you need to create a copy of the array you want to push. Otherwise all entrys in the array will be completly the same and you won't get the expected output (also see here)
function checkForThreefoldRepetition () {
let counter = 0;
for (let i = 0; i < positionList.length; i++) {
if (JSON.stringify(positionList[i]) === JSON.stringify(position)) {
counter++;
}
}
if (counter === 2) {
const updateGameOver = {
gameOver: true,
reason: "threefold repetition",
winner: "draw"
}
setGameOver(updateGameOver)
}
}
useEffect(() => {
let positionCopy = [];
for (let i = 0; i < position.length; i++) {
positionCopy[i] = position[i].slice();
}
setPositionList([...positionList, positionCopy]);
checkForThreefoldRepetition()
}, [playerTurn])
I think your problem is you are modifying current state directly like this one which is not a proper way of updating state :
positionList[i].counter = positionList[i].counter + 1
So this extra render cause problems,I think.

how to add an object to array immediately after set to empty "[ ]" Vue

I need after call a function, set to empty an array and immediately add a new one to there.
This is becouse when an #click event is called i need to call a dialog and populate the content of this with a dynamic component (called them with a slug propertie), so the array should be change accordily to pass the slug propertie to the component.
My code is:
slugs: []
slugConversacion(slug) {
if (this.slugs > 0) {
this.slugs = []
// this.slugs.splice(this.slugs.indexOf(slug), 0);
// this.$delete(this.slugs, this.slugs.indexOf(slug))
}
else {
this.slugs.push(slug);
}
}
<Conversacion
v-for="slug in slugs"
:key="slug.id"
:slug="slug.slug"
></Conversacion>
This not work because when i click the event slugConversacion() set and empty array and only when clicked again, populate. I think that is for the if/else conditional.
What would be the right approach ? Thanks!
Just do this:
if (this.slugs.length > 0) {
this.slugs = [];
}
this.slugs.push(slug);
If you have trouble with setting array to empty with assigning [] to array and loosing reactivity, then you can try next thing.
This works for me as the last resort:
var i = slugs.length;
while(i --){
slugs.splice(i, 1);
}
You should do splice in revers mode because of index confusion: every time will be remained array element with index 1 if you will go throw the loop via
slugs.forEach((item, index) => {
slugs.splice(index, 1);
});
And after that you can do:
this.slugs.push(slug);

javascript array pop without another foreach loop

my test array has multiple objects in them that I want to iterate over and if a condition is not met I want to pop it from main array.
I am using foreach loop. so
so I am using a foreach loop and doing
$.foreach(test, function(idx, val){
if(true){
test.splice(idx, 1);
}
});
problem is that it doesn’t work as if there are two objects for example, as shown below, it will reindex the array after the first iteration and then the second iteration which will be idx 1, will not be able to do
test.spice(1,1) since index 1 does not exist in the array anymore.
Now I know that I can create a temporary place holder and the indexes there and then run another foreach but thats what I am trying to avoid. Any ideas will be appreciated
[
email: “testemail#emailcom”
firstName: “Test"
]
[
email: “testemail2#emailcom”
firstName: “Test"
]
If you want to remove elements from an array, I recommend you to use filter function
test = test.filter(function(val, idx) {
if(true) { // a condition about val
return false; // return false to EXCLUDE
} else {
return true; // return false to INCLUDE
}
});
Just iterate through the array backwards. Then, removing elements from the array only affects the indices of elements that the loop has already dealt with:
for (var idx = test.length-1; idx>=0; idx--){
if(true){
test.splice(idx, 1);
}
}

as3 array remove by index

I have an array 'cat', 'dog', 'budgie'
and want to remove the item by index.
At the moment I have
function removeit(myindex) {
animals[myindex] = animals.pop()
}
You want splice
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#splice%28%29
Array.splice(starting point, remove count);
var newArray:Array = myArray.splice(2, 1); //this removes whatever is at index 2 and returns it in a new array.
Change your function to
function removeit(myindex) {
animals.splice(myindex, 1);
}
When using Flash Player 19+ or AIR 19+, you can use
myArray.removeAt(myIndex); // removes the element at the specified index, modifying the array without making a copy
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#removeAt()

How would I remove a "row" in an array depending on the value of an element?

Here's what I'm currently doing/trying to do to accomplish my goal. But it is not removing the "row" the way I would like it too.
So, I'm making an object, then pushing it into an array. And the adding to the array part works fine and just as I expect.
var nearProfileInfoObj:Object = new Object();
nearProfileInfoObj.type = "userInfo";
nearProfileInfoObj.dowhat = "add";
nearProfileInfoObj.userid = netConnection.nearID;
nearProfileInfoObj.username = username_input_txt.text;
nearProfileInfoObj.sex = sex_input_txt.selectedItem.toString();
nearProfileInfoObj.age = age_input_txt.selectedItem;
nearProfileInfoObj.location = location_input_txt.text;
nearProfileInfoObj.headline = headline_input_txt.text;
theArray.push(nearProfileInfoObj);
So after that later on I need to be able to remove that object from the array, and it's not working the way I'm expecting. I want to take a variable whoLeft and capture their ID and then look in the array for that particular ID in the userid part of the object and if its there DELETE that whole "row".
I know you can do a filter with an array collection but that doesnt actually delete it. I need to delete it because I may be adding the same value again later on.
whoLeft = theiruserIDVariable;
theArray.filter(userLeaving);
public function userLeaving(element:*, index:int, arr:Array):Boolean
{
if (element.userid == whoLeft)
{
return false;
}
else
{
return true;
}
}
But this doesnt seem to be deleting the whole row like it implies. Does anyone know what i'm doing wrong?
Instead of modifying the original array, the new filtered array is returned by the filter method. So you need to assign the returned array to theArray.
Try this
theArray = theArray.filter(userLeaving);
EDIT This turned out to be slower than for loop:
An alternative to the hand coded loop could be something like this:
theArray.every(searchAndDestroy);
public function searchAndDestroy(element:*, index:int, arr:Array):Boolean
{
if (element.userid == whoLeft)
{
arr.splice(index,1);
return false;
}
return true;
}
As far as I know, every() terminates the first time the test function returns false. So the question is: for a big list, which is faster, the for loop or the loop that every() does with the overhead of the test function call.
EDIT #2 But this was faster than a for loop for a test I ran on an array of a million Points:
for each(var element:Object in theArray)
{
if (element.userid==whoLeft)
{
theArray.splice(theArray.indexOf(element),1);
break;
}
}
I think this is what you're looking for:
for(var i:uint = 0, len:uint = theArray.length; i<len; i++)
{
if(thisArray[i].id == whoLeft.id)
{
thisArray.splice(i, 1);
break;
}
}
However, do you really need it in an Array because you could always use a Dictionary which would mean accessing it by id which would be a lot simpler to remove.

Resources