user15354331
user15354331

Reputation:

How to delete a list item in React Functional Component without using id

I am trying to create a simple to do page using react after adding to do list item i am attaching trash icon & when user click its required its corresponding list item is deleted , i want to know if it can be done without using id, for ex in jquery it was simple (this.remove )

 const [input, setValue] = useState("");
  const [todos, setTodos] = useState([]);
  // passing  entered
  const handleInput = (event) => {
    setValue(event.target.value);
  };

  const lp = (event) => {
    // let c = [1,2,34,55]

    event.preventDefault();
    // if no input nothing will happen return none
    if (!input) return;
    // using spread operator its used whenever we need to add array data to exiting array
    const newTodos = [...todos, input];

    setTodos(newTodos);
    // clearing input text
    setValue("");
  };
  const handeldel=(e) => {
//  how to delete
  
  }

  return (
    <div>
      <div class="input-group mb-3">
        <input
          className="form-control border-primary font-weight-bold"
          style={{ height: 60 }}
          placeholder="Enter Text here"
          type="text"
          value={input}
          onChange={handleInput}
        />
        <div class="input-group-append">
          <button
            className="input-group-append font-weight-bolder "
            style={{ fontSize: 20 }}
            onClick={lp}
          >
            {" "}
            <i class="fas fa-plus-square fa-2x p-2"></i>{" "}
          </button>
        </div>
      </div>

      {todos.map((x) => (
        <ol style={{ listStyle: "none" }}>
          <li className="font-weight-bolder table-bordered" style={{fontSize:20}}>
            {x} <i class="fas fa-trash-alt" onClick={handeldel}></i>
          </li>
        </ol>
      ))}
    </div>
  );
};

Upvotes: 3

Views: 1174

Answers (3)

Ezequiel S. Sandoval
Ezequiel S. Sandoval

Reputation: 170

As far as you're mapping an array to make a todos list there're a couple things you need to have in mind

When mapping arrays your node should have an unique key as default prop

// GOOD!!!
{todos.map(todo => (
  <ol key={todo.uniqueKey} {...rest}>
    ...
  </ol>
))}

You shouldn't pass index as your node key

// Don't do this, BAD!!!
{todos.map((todo, index) => (
  <ol key={index} {...rest}>
    ...
  </ol>
))}

Now, answering to your question, there's a simple way to do this, so i'll share with you the one i think is the best:

// Imagine you have these
const [todos, setTodos] = useState([
 { key: 'item1', content: 'some content' },
 { key: 'item2', content: 'some content' },
 { key: 'item3', content: 'some content' },
 { key: 'item4', content: 'some content' }
]);

// filter return a new array where the id is not like the one passed to handle del
// this is a function that returns a function
const handleDel = todoKey => e => setTodos(prev => prev.filter(todo => todo.key !== todoKey));

// Passing to the map you'll have something like
{todos.map(todo => (
  <ol key={todo.key} style={{ listStyle: "none" }}>
    <li className="font-weight-bolder table-bordered" style={{fontSize:20}}>
      {todo.content} <i class="fas fa-trash-alt" onClick={handleDel(todo.key)}></i>
    </li>
  </ol>
))}

If using above approach then you have to modify your lp and handleInput functions, i'm giving you a simple example

// Here you're setting the unique key with Date.now()
// You're assigning an object to store what you need and save it later
// in your todos list
const handleInput = e => setValue({ key: new Date.now(), content: e.target.value });

const lp = (event) => {
  event.preventDefault(); // as soon as it's not a submit button you don't need to preventDefault 
  if (!input) return;
  // You can access to your previous state from inside your setState
  // function, that's the same as you were doing but less verbose
  setTodos(prevTodos => ([...prevTodos, input]));
  // clearing input text
  setValue({ key: null, content: '' });
};

// In your input you'll need to change to this as far as you're setting state with an object

<input
  className="form-control border-primary font-weight-bold"
  style={{ height: 60 }}
  placeholder="Enter Text here"
  type="text"
  value={input.content} // <-- this is what you need to change
  onChange={handleInput}
/>

// to not have problems with useState always initialize it with what you
// will need, in this example your input state will change to this

const [input, setValue] = useState({
  key: null,
  content: ''
});

I hope this helps you to understand more about react and how it works (also to teach some good techniques in case you didn't know 'em)

Upvotes: 0

Surjeet Bhadauriya
Surjeet Bhadauriya

Reputation: 7166

You can use an index in order to delete the specific item from the list.

  const handeldel = (index) => {
    todos.splice(index, 1);
    setTodos([...todos]);      
  }

And then HTML

 {todos.map((x, index) => (
     <ol style={{ listStyle: "none" }}>
        <li className="font-weight-bolder table-bordered" style={{fontSize:20}}>
           {x} <i class="fas fa-trash-alt" onClick={() => handeldel(index)}></i>
        </li>
      </ol>
  ))}

Upvotes: 1

WebEXP0528
WebEXP0528

Reputation: 601

 const handeldel=(index) => {
  todos.splice(index, 1);
  }

todos.map((x, index) => (...
...
<i class="fas fa-trash-alt" onClick={(e)=>handeldel(index)}></i>

Upvotes: 1

Related Questions