React-native infinite re-renders - reactjs

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.

Related

React Native add to state array if value does not exist

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

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

Implementing undo/redo function in react

I am trying to implement simple undo/redo function in my react app. So I am trying to maintain an array with old state values. But when I check the values of the old states, its all updated with the new state.
state :
state = {
schedule : [],
loads:[],
undo:[],
redo:[]
};
const redoUndoObj ={
oldStateSchedule : [...this.state.schedule],
oldStateLoads : [...this.state.loads]
}
this.setState({ undo : [ ...this.state.undo , redoUndoObj]});
I hope this give you an idea on how to solve the problem. I made code only for undo now to point you in the right direction. This example I made via React functional component using useState instead of Component class.
const [schedule, setSchedule] = useState([]);
const [loads, setLoads] = useState([]);
const [undo, setUndo] = useState([]);
const [redo, setRedo] = useState([]);
const updateData = (newSchedule, newLoads) => {
setSchedule([...newSchedule]);
setLoads([...newLoads]);
const newUndo = {
schedule: [...newSchedule],
loads: [...newLoads],
};
setUndo([...undo, ...newUndo]);
}
const undoChanges = () => {
const lastElement = undo[undo.length - 1];
const copyOfUndo = [...undo];
// Update redo to be able to rollback
setRedo([...undo]);
// Set the previous values to Schedule and Loads
schedule([...lastElement.schedule]);
loads([...lastElement.loads]);
// Remove the last element from undo
lastElement.pop();
undo([...lastElement]);
}

React Hooks reversing syntax of useState - pretty strange

So I've used React Hooks somewhat heavily in the past few months on one particular project - this is the first time I've seen anything like this and was wondering if anybody had an explanation as to what is happening.
I have the following:
const [ setSectionDefects, sectionDefects ] = useState([]);
const { propertyDefects, propertySections } = props;
useEffect(()=> {
const defectsBySection = [];
propertySections.map(propertySection => {
const sectionId = propertySection.SectionId;
const defectArray = [];
const sectionObject = { id: sectionId, defects: defectArray };
propertyDefects.map(propertyDefect => {
if (propertyDefect.WosectionId == sectionId) {
defectArray.push(propertyDefect);
}
})
defectsBySection.push(sectionObject);
})
// setSectionDefects(defectsBySection);
// sectionDefects(defectsBySection);
}, []);
console.log(setSectionDefects, sectionDefects)
When the code reaches the console.log statement, it says that 'setSectionDefects' is an array and 'sectionDefects' is the function to set it!
My mind is blown, I can't figure it out for the life of me - the syntax, as I've learned it, is the function declaration first, and then the variable to be set -
ie: const [ setSectionDefects, sectionDefects ] = useState([]);
Has anyone else ran into this?
the first item in useState is the state itself and and second item is function to update it.
https://reactjs.org/docs/hooks-reference.html#usestate.
In your case just swipe the names.
const [ sectionDefects , setSectionDefects] = useState([]);
You have array destructuring the wrong way around.
It should be:
const [ sectionDefects, setSectionDefects ] = useState([]);

Should I use useMemo in hooks?

I created useBanner hooks
const useBanner = (array, yardage) => {
const [bannArr, setBannArr] = useState(array.slice(0, yardage));
const [bannListIndex, setBannIndex] = useState(1);
return {
....
};
};
Am I doing the right thing and the props throw in useState.
It’s permissible to use useBanner.
const Banner= ({
array,
yardage
}) => {
const { bannForth, bannBeck, bannArr } = useBanner(array, yardage);
return (
...
);
};
when props will change here.
Will change the state in useBanner.
or is it considered anti-patterns I have to write all this in useMemo
const useBanner = (array, yardage) => {
const [bannArr, setBannArr] = useState([]);
const [bannListIndex, setBannIndex] = useState(1);
useMemo(() => {
setBannArr(array.slice(0, yardage));
setBannIndex(1);
}, [array, yardage]);
return {
....
};
};
Yes, custom hooks are possible in React. Here is separate document discussing custom hooks.
But exactly you sample may require additional code depending on what is your final goal.
If you want initialize state only once, when component Banner is first created, you can just do as in your first sample
const Banner= ({
array,
yardage
}) => {
const { bannForth, bannBeck, bannArr } = useBanner(array, yardage);
return (
...
);
};
This will work perfectly. But if props array and yardage will change, this will not be reflected in component. So props will be used only once as initial values and then will not be used in useBanner even if changed (And it doesn't matter whether you'll use useBanner or useState directly). This answer highlight this.
If you want to update inital values on each props change, you can go with useEffect like below
const Banner= ({
array,
yardage
}) => {
const { bannForth, bannBeck, bannArr, setBannArr } = useBanner(array, yardage);
useEffect (() => {
// setBannArr should also be returned from useBanner. Or bannArr should be changed with any other suitable function returned from useBanner.
setBannArr(array.slice(0, yardage));
}, [array, yardage, setBannArr])
return (
...
);
};
In this case Banner component can control state itself and when parent component change props, state in Banner component will be reset to new props.
Here is small sample to showcase second option.

Resources