skip to Main Content

Here is what happening try to add 3 sections then delete the section content 2, It is supposed to delete that section but this is not what happened. I think I missed something in the code or in the handleDelete.

Below is my code and also here is the online code.

import { useState } from "react";
import styled from "styled-components";

const AddSection = styled.div`
  padding: 1rem;
  border: 1px solid blue;
  margin: 1rem 0;
  position: relative;
`;

const CloseBtn = styled.div`
  position: absolute;
  right: -0.5rem;
  top: -0.5rem;
  background-color: orange;
  font-size: 1rem;
  padding: 0.1rem 0.7rem;
  border-radius: 0.5rem;
  cursor: pointer;
`;

export default function App() {
  const [val, setVal] = useState([]);
  const handleAdd = () => {
    const addValue = [...val, []];
    setVal(addValue);
  };
  const handleDelete = (index) => {
    const deleteValue = [...val];
    deleteValue.splice(index, 1);
    setVal(deleteValue);
  };
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <div className="m-container">
        {val.map((element, index) => {
          return (
            <AddSection key={index} draggable="true">
              <div>Section Content {index + 1}</div>
              <CloseBtn onClick={() => handleDelete(index)}>x</CloseBtn>
            </AddSection>
          );
        })}
        <button onClick={() => handleAdd()}>Add Section</button>
      </div>
    </div>
  );
}

2

Answers


  1. const handleDelete = (index) => {
      setVal(prevState => {
        const deleteValue = [...prevState];
        deleteValue.splice(index, 1);
        return deleteValue;
      });
    };
    

    I modified your code that ensures immutability, with this using the functional form of setVal, you are guaranteed to be working with the latest state, it also helps avoid potential issues with statle state data in asynchronous nature of state updates

    Login or Signup to reply.
  2. It’s a bad idea to use index as their content and key.

    If you really want to use index, you can just hide them so their index won’t change.

    const {
      useState
    } = React;
    
    const AddSection = styled.div `
      padding: 1rem;
      border: 1px solid blue;
      margin: 1rem 0;
      position: relative;
    `;
    
    const CloseBtn = styled.div `
      position: absolute;
      right: -0.5rem;
      top: -0.5rem;
      background-color: orange;
      font-size: 1rem;
      padding: 0.1rem 0.7rem;
      border-radius: 0.5rem;
      cursor: pointer;
    `;
    
    function App() {
      const [val, setVal] = useState([]);
      const handleAdd = () => setVal((prev) => [...prev, {
        show: true
      }]);
      const handleDelete = (index) => setVal((prev) => prev.map((v, i) => (i == index ? { ...v,
        show: false
      } : v)));
      return ( <
        div className = "App" >
        <
        h1 > Hello CodeSandbox < /h1> <
        h2 > Start editing to see some magic happen! < /h2> <
        div className = "m-container" > {
          val.map((element, index) => {
            if (element.show)
              return ( <
                AddSection key = {
                  index
                }
                draggable = "true" >
                <
                div > Section Content {
                  index + 1
                } < /div> <
                CloseBtn onClick = {
                  () => handleDelete(index)
                } > x < /CloseBtn> <
                /AddSection>
              );
          })
        } <
        button onClick = {
          () => handleAdd()
        } > Add Section < /button> <
        /div> <
        /div>
      );
    }
    
    ReactDOM.createRoot(document.querySelector("#App")).render( < App / > );
    .App {
      font-family: sans-serif;
      text-align: center;
    }
    
    .m-container {
      max-width: 600px;
      margin: auto;
    }
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/styled-components/6.1.1/styled-components.min.js" integrity="sha512-4iEUioskYwCuxaoe1h1cy8cVKoo5WyZfFzX+S0PrPh+oLzB/rMXkF6dOH2UFBwvUDrsghDHqua3D+OywaRhOXw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <div id="App"></div>

    A better way to do that is to add unique id when add section.

    const {
      useState
    } = React;
    
    const AddSection = styled.div `
      padding: 1rem;
      border: 1px solid blue;
      margin: 1rem 0;
      position: relative;
    `;
    
    const CloseBtn = styled.div `
      position: absolute;
      right: -0.5rem;
      top: -0.5rem;
      background-color: orange;
      font-size: 1rem;
      padding: 0.1rem 0.7rem;
      border-radius: 0.5rem;
      cursor: pointer;
    `;
    
    function App() {
      const [currentId, setCurrentId] = useState(1);
      const [val, setVal] = useState([]);
      const handleAdd = () => {
        setVal((prev) => [...prev, {
          id: currentId
        }]);
        setCurrentId((prev) => prev + 1);
      };
      const handleDelete = (element) => setVal((prev) => prev.filter((e) => e !== element));
      return ( <
        div className = "App" >
        <
        h1 > Hello CodeSandbox < /h1> <
        h2 > Start editing to see some magic happen! < /h2> <
        div className = "m-container" > {
          val.map((element) => {
            return ( <
              AddSection key = {
                element.id
              }
              draggable = "true" >
              <
              div > Section Content {
                element.id
              } < /div> <
              CloseBtn onClick = {
                () => handleDelete(element)
              } > x < /CloseBtn> <
              /AddSection>
            );
          })
        } <
        button onClick = {
          () => handleAdd()
        } > Add Section < /button> <
        /div> <
        /div>
      );
    }
    
    ReactDOM.createRoot(document.querySelector("#App")).render( < App / > );
    .App {
      font-family: sans-serif;
      text-align: center;
    }
    
    .m-container {
      max-width: 600px;
      margin: auto;
    }
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/styled-components/6.1.1/styled-components.min.js" integrity="sha512-4iEUioskYwCuxaoe1h1cy8cVKoo5WyZfFzX+S0PrPh+oLzB/rMXkF6dOH2UFBwvUDrsghDHqua3D+OywaRhOXw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <div id="App"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search