Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

239
Views
Why doesn't my UI properly rerender my deleted object?

I have a parent component that maps over a list state using an Input component

import "./styles.css";
import { useState, useEffect } from "react";
import Input from "./Input";

export default function App() {
  const [list, setList] = useState([{}]);
  useEffect(() => {
    console.log("list", list);
  }, [list]);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {list.map((_, i) => (
        <div key={i}>
          <Input id={i} setList={setList} />
        </div>
      ))}
    </div>
  );
}

Submitting each Input leaves another Input available for submission. However, when I delete each Input, I see that the data object is gone but the UI doesn't reflect this.

import { useState } from "react";

const Input = ({ setList, id }) => {
  const [value, setValue] = useState("");
  const [submitted, setSubmitted] = useState(false);
  const handleChange = (event) => {
    const result = event.target.value.replace(/\D/g, "");
    setValue(result);
  };
  const handleSubmit = () => {
    setList((list) => [...list, { id: id, total: value }]);
    setSubmitted(true);
  };
  const handleDelete = () => {
    console.log("id", id);
    setList((list) => list.filter((item) => item.id !== id));
  };
  return (
    <div>
      <input
        value={new Intl.NumberFormat("ko-KR", {
          style: "currency",
          currency: "KRW"
        }).format(Number(value))}
        onChange={handleChange}
        type="text"
      />
      {submitted ? (
        <button disabled={value.length === 0} onClick={handleDelete}>
          Delete
        </button>
      ) : (
        <button disabled={value.length === 0} onClick={handleSubmit}>
          Submit!
        </button>
      )}
    </div>
  );
};

export default Input;

I suspect that this is because

  const [list, setList] = useState([{}])

Is initialized with an empty object, and that is causing the problem. However, I need at least one object inside the list state so I can have the initial Input component for submission.

How do I properly delete my Input component?

My codesandbox

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Your issue is with your key

<div key={i}></div>

React uses the key prop to help identify what elements have been changed. Keys should remain the same for each element in your array across re-renders, so that React can identify when an element has been updated based on a state change. As you're removing elements from your state, the index doesn't serve as a stable key that is uniquely associated with your object (as objects shift into lower indexes when one is removed). Instead, it's best to add some sort of id associated with the elements that you render:

const [list, setList] = useState([{ id: 0}]);
...
{list.map(({ id }) => (
  <div key={id}>
    <Input id={id} setList={setList} />
  </div>
))}
...

Then in your component where you add your objects, you can create a new id (which doesn't change) for each new object. Below I've used Math.random(), but you should use something more reliable than that (eg: uuidv4).

setList((list) => [...list, { id: Math.random(), total: value }]);

You should also look into how you're adding new values. The "submit" Input only appears because of the new object that you're adding to your list: { id: Math.random(), total: value }. I would instead have App display one Input which is primarily responsible for adding items to your list state, and then have each Input that is rendered within the .map() take care of the "delete" functionality.

about 4 years ago · Juan Pablo Isaza Report

0

This happen because you used index as a key in map.

You can read more about it here.

Long story short, for example you have 3 items, you delete second that has key "2", then your third element receive a key "2" and react think that this is the same element.

I updated your example with item template that have temp id set to "new item" and used id as a key.

Also I create id for each new element in handleSubmit function, so your temp id never became a real one.

Here is updated code. I removed some code that wasn't changed.

App component

const TEMPLATE = {
  id: "new item",
  value: 0,
}

export default function App() {
  const [list, setList] = useState([{...TEMPLATE}]);

  return (
    <div className="App">
      {list.map((item) => (
        <div key={item.id}>
          <Input id={item.id} setList={setList} />
        </div>
      ))}
    </div>
  );
}

And here is Input component. You would want to generate Id in some other way.

const Input = ({ setList, id }) => {
  ...
  const handleSubmit = () => {
    setList((list) => [...list, { id: Math.random(), total: value }]);
    setSubmitted(true);
  };
  ...    
};
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!