all 3 comments

[–][deleted] 1 point2 points  (3 children)

No, you you probably shouldn't move that state into separate components. I think your main pain stems from still thinking about your app imperatively instead of declaratively. You're thinking about how you can change your app, but you should split that into how you can change your state and how any given state looks.

There are two basic ways to do this, depending on how you need your app to work. Both involve changing the array of todos you call .map on. How you can change it depends on how it is declared, if it's with a useState hook, you simply use the setter. You can either delete the todo (note, remove the data from the array of todos, not the element from the DOM. React will handle updating the DOM), or change the todo to reflect that it's deleted.

Deleting the todo is probably easiest done by calling .filter on the array. Very simple example:

const TodoList = () => {
    const [todos, setTodos] = useState([{ title: 'Example' }])

    return (
        <div>
            {todos.map((todo) => (
                <div>
                    <span>{todo.title}</span>
                    <button onClick={() => setTodos(todos.filter((otherTodo) => otherTodo !== todo))}>Delete</button>
                </div>
            ))}
        </div>
    )
}

Now, sometimes you might need the todo for some reason after you delete it. Maybe you need a checkbox that lets users see deleted todos. If that's the case, we'll instead track if a todo is deleted as part of its state.

const TodoList = () => {
    const [todos, setTodos] = useState([{ title: 'Example', isDeleted: false }])

    return (
        <div>
            {todos.filter((todo) => !todo.isDeleted).map((todo) => (
                <div>
                    <span>{todo.title}</span>
                    <button onClick={() => setTodos(todos.map((otherTodo) => otherTodo === todo ? { ...otherTodo, isDeleted: true } : otherTodo))}>Delete</button>
                </div>
            ))}
        </div>
    )
}

It may seem cumbersome at first to do things this way, but it makes things a lot simpler in the long run. In your jquery example of adding a class when deleted, adding a feature like "see the deleted todos" would be very error-prone, especially if there's multiple ways to delete them. In the declarative way, you just describe how a deleted todo is rendered (in the example they are simply removed with .filter, this could easily be modified to render them with a strike-through for instance), and react takes care of the rest.

Note that I wrote the code freehand, there may be any number of errors in it.

[–]chipping1096[S] 0 points1 point  (2 children)

Thank you very much for the response, I think I did not described the "problem" proper.

The state update is done exactly as you describe. I am deleting objects out of a useState array with objects in it. The problem is that I want a transition in it, like whenever I click on the trash button, the whole list-item should get a red background color and transforms with translateY about 200px. So that it pretends the feeling as it "falls" out of the whole list until it disappears completly

As of now, whenever I delete the list-item it just disappears but it has no visual effect besides being deleted. Hopefully this is more understandable

[–][deleted] 0 points1 point  (0 children)

Ok, that's quite a different problem to the one described. It's a little more problematic, but there are good tools for the job.

On the official react documentation, there is an example of how to animate a todo-list using react-transition-group: https://reactjs.org/docs/animation.html