0

I'm currently developing an application using React Native.

This trial app has two buttons (ADD and DELETE).

When I press the ADD Button, a new component appears. If I press the DELETE Button that the same component disappears.


My question is: why can't I delete components one by one in this code?

even though I select an index of components I want to delete, all components disappear when I press a DELETE button...

How can I resolve this problem?


Here is the code (Screen):

import React, { useState } from "react";
import { ScrollView } from "react-native";
import Items from "../components/Items";

export default function Screen() {
  const items = {
    lists: [""],
  };

  const [stateItems, setStateItems] = useState(items);

  return (
    <ScrollView>
      <Items stateItems={stateItems} setStateItems={setStateItems} />
    </ScrollView>
  );
}

Here is the code (Components):

import React from "react";
import { StyleSheet, View, Text, TouchableOpacity } from "react-native";

function Item({ index, handleAdd, handleDelete }) {
  return (
    <View style={styles.list}>
      <TouchableOpacity
        onPress={() => {
          handleDelete(index);
        }}
        style={styles.buttonDelate}
      >
        <Text>DELETE</Text>
      </TouchableOpacity>
      <TouchableOpacity
        onPress={() => {
          handleAdd();
        }}
        style={[styles.buttonDelate, styles.buttonAdd]}
      >
        <Text>ADD</Text>
      </TouchableOpacity>
    </View>
  );
}

export default function Items(props) {
  const stateItems = props.stateItems;
  const setStateItems = props.setStateItems;

  const handleAdd = () => {
    setStateItems({
      ...stateItems,
      lists: [...stateItems.lists, ""],
    });
  };

  const handleDelete = (index) => {
    const ret = stateItems.lists;
    setStateItems({ ...ret, lists: [...ret].splice(index, 1) });
  };

  return (
    <View>
      {stateItems.lists.map((value, i) => (
        <Item
          key={value + i.toString()}
          index={i}
          stateItems={stateItems}
          setStateItems={setStateItems}
          handleAdd={handleAdd}
          handleDelete={handleDelete}
        />
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  list: {
    width: "100%",
    backgroundColor: "#ddd",
    margin: 5,
    padding: 10,
  },
  buttonDelate: {
    backgroundColor: "tomato",
    width: 80,
    height: 40,
    borderRadius: 5,
    margin: 3,
    justifyContent: "center",
    alignItems: "center",
    alignSelf: "center",
  },
  buttonAdd: {
    backgroundColor: "orange",
  },
});

node : 12.18.3

react native : 4.10.1

expo : 3.22.3

Emile Bergeron
  • 14,368
  • 4
  • 66
  • 111
Tio
  • 500
  • 1
  • 4
  • 13

1 Answers1

2

Splice returns the deleted items, not the original array. So when you do:

setStateItems({ ...ret, lists: [...ret].splice(index, 1) });

you're setting lists to the items deleted from [...ret], not the remaining ones.


We might also want to address why you're spreading the list into state and also setting lists to the deleted items from a copy of the original ret array.

const handleDelete = (index) => {
  const ret = stateItems.lists;
  setStateItems({ ...ret, lists: [...ret].splice(index, 1) });
};

The first part of this is stomping your other state with the lists array, which I highly doubt is what you want. Maybe you intended to preserve other state properties? Something more like:

const handleDelete = (index) => {
  const { lists: old, ...others } = stateItems;
  const lists = [...old];
  lists.splice(index, 1);
  setStateItems({ ...others, lists });
};
ray hatfield
  • 16,302
  • 4
  • 25
  • 21