I want to filter each task (item) but my code doesn't work My purpose is when I click on each div the div disappears but it doesn't work
const { useState, Fragment } = React;
const tasks = [
{
id: 1,
title:
"sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
},
{
id: 2,
title: "qui est esse",
body: "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
},
{
id: 3,
title: "ea molestias quasi exercitationem repellat qui ipsa sit aut",
body: "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
},
];
/*export default*/ function Tasks() {
const [initial_tasks, setTasks] = useState(tasks);
const onDelete = (id) => {
setTasks(initial_tasks.filter((task) => task.id !== id));
};
return (
<Fragment>
{tasks.map((task) => (
<div
style={{ border: "1px solid red" }}
onClick={() => {
onDelete(task.id);
}}
>
<h1>{task.id}</h1>
<p>{task.title}</p>
</div>
))}
</Fragment>
);
}
ReactDOM.createRoot(document.getElementById("root"))
.render(<Tasks />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.0/umd/react-dom.development.js"></script>
CodePudding user response:
heres the mistakes you made
1: you need to mention the state variable in the map so when it change it get effected
2: dont filter intial_tasks the setTask function gives you the old value so make use of it
3: you need to provide key prop in the div so react knows what element has been changed
import { useState } from "react";
const tasks = [
{
id: 1,
title:
"sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
},
{
id: 2,
title: "qui est esse",
body: "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
},
{
id: 3,
title: "ea molestias quasi exercitationem repellat qui ipsa sit aut",
body: "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
},
];
export default function App() {
const [initial_tasks, setTasks] = useState(tasks);
const onDelete = (id) => {
setTasks(oldTasks => {
return oldTasks.filter((task) => task.id !== id)
});
};
return (
<>
{
initial_tasks.map((task) => (
<button key={task.id} style={{ border: "1px solid red" }} onClick={() => onDelete(task.id)} >
<h1>{task.id}</h1>
<p>{task.title}</p>
</button>
))
}
</>
);
}
CodePudding user response:
Your tasks variable is not attached to a state. Your tasks variable is what your using to map in the render. So that means between renders changes may be lost. You need to assign your array to a state instead.
const [taskList, setTaskList] = useState(tasks);
You need to ensure you then use the getter of this state to be the target of your map. So taskList is what you need to map.
It's also important to remember not to mutate a state array directly. So when you want to add a new item to the array. You maybe tempted to write
taskList.push(newTask)
But that isn't right. Technically it would work but it wouldn't be flagged as a state update and anything subscribed to that state wouldn't update with the new value until a state update occurs. So instead you should copy the state, push to that array, and then assign it back. Here's an example
const addTask = (myTask) => {
//make a copy of the state
const state = [...taskList]
//push new task
state.push(myTask)
//assign new state
setTaskList(state)
}
In your filtering example, this could likely be done in a single one line set state
setTaskList(prvState => prvState.filter(task => task.id !== someValue));
This works because filter returns a new array, not a mutation of your original array.