Basically, every time I select an element (in this case a photo), the details of that element are inserted into the array called "photoArray". When the length of the photoArray is greater than or equal to 2 set the "isComparable" status to true. The display of a comparison button depends on the value of this state. That said, the problem lies in the fact that when I call the React setIsComparable method to set the state, this operation resets the photoArray from time to time, leaving it full of the data of the last selected image and not of all those selected, up to that moment, as it should be. The very strange thing is that if I avoid calling the setState everything works correctly. How can a setState cause an array to be reset?
For convenience, I am attaching a Snack that shows the exact functioning of my code and the problem I have described to you.
Ps.: unfortunately from the Snack in the "web" version the images are not seen, but from the "Android" or "iOS" device the simulation is perfectly congruent with my app
EXPO SNACK: https://snack.expo.io/@sido95/array-push-not-work
You declared an empty array which automatically re-initializes on re-render.
Instead declare photoArray
as a variable using useState
This works perfectly fine
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, FlatList } from 'react-native';
import Constants from 'expo-constants';
import { ProgressCard } from './components/progressCard';
import { NativeBaseProvider, Button } from 'native-base';
export default function App() {
const [isComparable, setIsComparable] = useState(false);
const [photoArray, SetphotoArray] = useState([]);
useEffect(() => {
setIsComparable(photoArray.length >= 2 ? true : false);
}, [photoArray]);
const compareFunc = (group, path) => {
//il gruppo di quella selezionata esiste già nell'array?
var elementPos = photoArray
.map(function (x) {
return x.group;
})
.indexOf(group);
if (elementPos != -1) {
//se esiste devo gestirlo come switch
//controllo se è uno switch o una rimozione
if (photoArray[elementPos].path != path) {
let temp = [...photoArray];
temp[elementPos].path = path;
SetphotoArray(temp);
} else {
let temp = [...photoArray];
temp.splice(elementPos, 1);
SetphotoArray(temp);
}
} else {
let temp = [...photoArray];
temp.push({ group: group, path: path });
SetphotoArray(temp);
}
console.log('photoArray.length', photoArray.length);
console.log('photoArray', photoArray);
};
const DATA = [
{
path1: 'FOTO1',
path2: 'FOTO2',
path3: 'FOTO3',
},
{
path1: 'FOTO1',
path2: 'FOTO2',
path3: 'FOTO3',
},
{
path1: 'FOTO1',
path2: 'FOTO2',
path3: 'FOTO3',
},
];
const renderItem = ({ item, index }) => {
return (
<ProgressCard
compare={compareFunc}
group={index}
path1={item.path1}
path2={item.path2}
path3={item.path3}
/>
);
};
return (
<NativeBaseProvider>
<FlatList
marginRight={10}
marginLeft={10}
data={DATA}
renderItem={renderItem}
keyExtractor={(item, index) => index}
/>
{isComparable && <Button>OK</Button>}
</NativeBaseProvider>
);
}
Kartikey Vaish is correct. In addition you should also avoid using mutations (like push
and splice
) on your react state as well. React will not will not pick up on these changes in state thus will not rerender correctly. Opted for Array
methods like map
, filter
and reduce
that create new array and leave your state untouched. By using these methods you can make the compareFunc
a bit more concise.
const compareFunc = (group, path) => {
let elementPos = photoArray.findIndex(e => e.group === group);
if (elementPos !== -1) {
SetphotoArray(photoArray.reduce((acc, photo, index) => {
if(elementPos === index) {
return photo.path === path ? acc : [...acc, {group: photo.group, path: path}];
}
return [...acc, photo]
}, []));
} else {
SetphotoArray([...photoArray, { group: group, path: path }]);
}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.