简体   繁体   中英

React Native setState does not make array.push work

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM