James Shih
James Shih

Reputation: 1

React not rendering new state

I am trying to learn the new React hooks. I have written a simple todolist that users can type in input to create a new todo, and click on the todo to remove it. However, it is not re-rendering after an todo item is removed.

Here is my code

import React, { useState, Fragment } from "react";

const Todo = () => {
  const [inputVal, setInput] = useState("");
  const [list, setList] = useState([]);
  const handleInput = e => {
    setInput(e.target.value);
  };
  const handleClick = () => {
    setList([...list, inputVal]);
    setInput("");
  };
  const handleDelete = index => {
    setList([...list.splice(index, 1)]);
    console.log(list);
  };
  const renderList = () =>
    list.map((item, index) => {
      return (
        <div key={index} onClick={() => handleDelete(index)}>
          {item}
        </div>
      );
    });
  return (
    <Fragment>
      <div>
        <input value={inputVal} onChange={handleInput} />
        <button onClick={handleClick}>submit</button>
      </div>
      <ul>{renderList()}</ul>
    </Fragment>
  );
};

export default Todo;

Upvotes: 0

Views: 83

Answers (1)

Simon Crane
Simon Crane

Reputation: 2182

You have two issues here.

  1. array.splice is mutating and returns the removed items. When you run
setList([...list.splice(index, 1)]);

This removes one item from the object list and then calls setList([removed_item]).

You could replace this line with

setList(list.slice(0, index).concat(list.slice(index + 1))

What is currently happening is that you are setting the state as the same object as before (but mutated), so it doesn't trigger a re-render.

  1. You are not using key attributes correctly. You can read the docs here

We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state.

Your keys should uniquely identify the elements of the todo list, without reference to the list itself. The text in the item is a good choice, except for the possible problem of non-uniqueness.

When you re-render the todo list, React uses the keys to decide which children to re-render. If you use indexes as keys, and then remove the item at index 0, then the 0th child will not be told to update to the new 0th element because it still gets the same key.

Upvotes: 1

Related Questions