React Native add to state array if value does not exist - reactjs

I would like to know the best way to add a value to an array of the value does not exist in my state variable. The current code works but I a newbie and not sure if I am doing this correctly. This function is fired when a button is pressed
const App = () => {
const [answered, setAnswered] = useState([])
const handleConnectionAnswer = deviceId => {
if (!anwsered.includes(deviceId)) {
setAnswered(prev => [...prev, deviceId]);
}
};
}

you're doing it right or you can simply do it like
if (!anwsered.includes(deviceId)) {
setAnswered([...answered, deviceId]);
}

Related

React state is not updating immediately after setState is being called

I am building the frontend of a web based software and I want to add new note every time I press add button.
But it's simply not happening. New note is being rendered only when I change the state of another object. Right below I ma attaching the code. Please help, I am stuck here.
const [allnotes, setAllNotes] = useState(notes)
const addNote = () => {
let notesAllTemp = allnotes;
allnotes.forEach((n, index) => {
if((n.id === clickedId)){
notesAllTemp[index].notesDescs.push({id:
notesAllTemp[index].notesDescs.length+1,desc:''})
setAllNotes(notesAllTemp)
}
});
}
If anyone can figure this out, please help.
Please don't make mistake by directly updating the array element by its index you should first copy the array into a new array, otherwise, it will directly update the array which will cause reacjs to not to re-render the component.
Check this out
const [allnotes, setAllNotes] = useState(notes)
const addNote = () => {
let notesAllTemp = [...allnotes]; // !IMPORTANT to copy array
allnotes.forEach((n, index) => {
if((n.id === clickedId)){
notesAllTemp[index].notesDescs.push({id:
notesAllTemp[index].notesDescs.length+1,desc:''})
}
});
setAllNotes(notesAllTemp);
}
Better if you first modify the array then update at once
const [allnotes, setAllNotes] = useState(notes)
const addNote = () => {
let notesAllTemp = allnotes;
allnotes.forEach((n, index) => {
if((n.id === clickedId)){
notesAllTemp[index].notesDescs.push({id:
notesAllTemp[index].notesDescs.length+1,desc:''})
}
});
setAllNotes(notesAllTemp)
}

Cannot update a component while rendering a different Component - ReactJS

I know lots of developers had similar kinds of issues in the past like this. I went through most of them, but couldn't crack the issue.
I am trying to update the cart Context counter value. Following is the code(store/userCartContext.js file)
import React, { createContext, useState } from "react";
const UserCartContext = createContext({
userCartCTX: [],
userCartAddCTX: () => {},
userCartLength: 0
});
export function UserCartContextProvider(props) {
const [userCartStore, setUserCartStore] = useState([]);
const addCartProduct = (value) => {
setUserCartStore((prevState) => {
return [...prevState, value];
});
};
const userCartCounterUpdate = (id, value) => {
console.log("hello dolly");
// setTimeout(() => {
setUserCartStore((prevState) => {
return prevState.map((item) => {
if (item.id === id) {
return { ...item, productCount: value };
}
return item;
});
});
// }, 50);
};
const context = {
userCartCTX: userCartStore,
userCartAddCTX: addCartProduct,
userCartLength: userCartStore.length,
userCartCounterUpdateCTX: userCartCounterUpdate
};
return (
<UserCartContext.Provider value={context}>
{props.children}
</UserCartContext.Provider>
);
}
export default UserCartContext;
Here I have commented out the setTimeout function. If I use setTimeout, it works perfectly. But I am not sure whether it's the correct way.
In cartItemEach.js file I use the following code to update the context
const counterChangeHandler = (value) => {
let counterVal = value;
userCartBlockCTX.userCartCounterUpdateCTX(props.details.id, counterVal);
};
CodeSandBox Link: https://codesandbox.io/s/react-learnable-one-1z5td
Issue happens when I update the counter inside the CART popup. If you update the counter only once, there won't be any error. But when you change the counter more than once this error pops up inside the console. Even though this error arises, it's not affecting the overall code. The updated counter value gets stored inside the state in Context.
TIL that you cannot call a setState function from within a function passed into another setState function. Within a function passed into a setState function, you should just focus on changing that state. You can use useEffect to cause that state change to trigger another state change.
Here is one way to rewrite the Counter class to avoid the warning you're getting:
const decrementHandler = () => {
setNumber((prevState) => {
if (prevState === 0) {
return 0;
}
return prevState - 1;
});
};
const incrementHandler = () => {
setNumber((prevState) => {
return prevState + 1;
});
};
useEffect(() => {
props.onCounterChange(props.currentCounterVal);
}, [props.currentCounterVal]);
// or [props.onCounterChange, props.currentCounterVal] if onCounterChange can change
It's unclear to me whether the useEffect needs to be inside the Counter class though; you could potentially move the useEffect outside to the parent, given that both the current value and callback are provided by the parent. But that's up to you and exactly what you're trying to accomplish.

React-native infinite re-renders

I am build a replica of the 2048 game.
I am working on the animations right now and I seem to get infinite re-renders for some reason when updating the state with any kind of array.
It seems that passing anything but an array to 'setAppearAnimations' works fine.
Thanks in advance :)
const GameProvider = (props) => {
const [appearAnimations, setAppearAnimations] = useState([])
const addAppearAnimation = (animation) => {
const newAppearAnimations = appearAnimations.concat([animation])
console.log(newAppearAnimations)
setAppearAnimations(newAppearAnimations)
}
const Piece = ({ piece }) => {
const { value, prevX, prevY, x, y, hasJustAppeared } = piece
let appearAnimation = 1
useEffect(() => {
//Add appear animation
if (hasJustAppeared) {
appearAnimation = new Animated.Value(0)
addAppearAnimation(appearAnimation)
}
}, [])
I changed the way the animations are being called so now i declare it inside A Piece component and start it inside a 'useEffect' inside it.

How I add an object to an existing array? React

recently I started to work in a proyect and I notice that I need some way to modify a value without losing my previous state. Basically work with an array. However I don't know how to do that.
Can anyone help me by telling me how can I modify an state (I'm using react hooks by the way...) to add more values to the previous state in an array?
Sorry not posting code or something like that, I don't even know how to write that.
Thank you in advance.
Use ES6 spread operator to push new object to the existing array.
Adding a new object to an Array:
const [todo, setTodo] = useState([{ task: "Todo 1" }]);
const addTodo = () => {
let newTodoTask = { task: `Task ${todo.length + 1}` };
setTodo(tasks => [...tasks, { ...newTodoTask }]);
};
Modifying an object in an Array:
const editTask = (e, taskId = 0) => {
setTodo(tasks =>
tasks.map((task, idx) =>
idx === taskId ? { task: "Edited Todo 1" } : { ...task }
)
);
};
Deleting an object from an array
const deleteTask = (e, taskId = 0) => {
setTodo(tasks => tasks.filter((task, idx) => idx !== taskId));
};
Find the simple working example here.
https://codesandbox.io/s/unruffled-elgamal-h7fhg?file=/src/App.js:482-593
First, Learn basic ES6 before start working on the project.
You can use the previous value returned from the setState to update the existing Array
import { useState } from 'react';
export default function Test() {
const [state, setstate] = useState([1,2,3,4);
return <div onClick={() => setstate((prev) => [...prev,99])}>Heyy{state}</div>;
}

ReactJs UseState : insert element into array not updating

I am trying to use React Hooks but somehow my state is not updating. When I click on the checkbox (see in the example), I want the index of the latter to be added to the array selectedItems, and vice versa
My function looks like this:
const [selectedItems, setSelectedItems] = useState([]);
const handleSelectMultiple = index => {
if (selectedItems.includes(index)) {
setSelectedItems(selectedItems.filter(id => id !== index));
} else {
setSelectedItems(selectedItems => [...selectedItems, index]);
}
console.log("selectedItems", selectedItems, "index", index);
};
You can find the console.log result
here
An empty array in the result, can someone explain to me where I missed something ?
Because useState is asynchronous - you wont see an immediate update after calling it.
Try adding a useEffect which uses a dependency array to check when values have been updated.
useEffect(() => {
console.log(selectedItems);
}, [selectedItems])
Actually there isn't a problem with your code. It's just that when you log selectedItems the state isn't updated yet.
If you need selectedItems exactly after you update the state in your function you can do as follow:
const handleSelectMultiple = index => {
let newSelectedItems;
if (selectedItems.includes(index)) {
newSelectedItems = selectedItems.filter(id => id !== index);
} else {
newSelectedItems = [...selectedItems, index];
}
setSelectedItems(newSelectedItems);
console.log("selectedItems", newSelectedItems, "index", index);
};

Resources