I am creating a shopping cart lit application, in that program add functionality is fine but when I add one list then another
enter code here
and then remove the one that is fine but when you want to delete two that is not able to deleted, also using the key={index} for identify each elements so what is the problem?
import { useReducer, useRef } from "react";
export default function App() {
const inputRef = useRef();
const [items, dispatch] = useReducer((state, action) => {
switch (action.type) {
case "add":
return [
...state,
{
id: state.length,
name: action.name
}
];
case "remove":
return state.filter((x) => x.id !== action.index);
default:
return state;
}
}, []);
function handleSubmit(e) {
e.preventDefault();
if (inputRef.current.value !== "") {
dispatch({
type: "add",
name: inputRef.current.value
});
}
inputRef.current.value = "";
}
return (
<div className="App">
<form onSubmit={handleSubmit}>
<input ref={inputRef} />
</form>
<ul>
{items.map((item, index) => (
<li key={index}>
{item.name}
<button onClick={() => dispatch({ type: "remove", index })}>
X
</button>
</li>
))}
</ul>
</div>
);
}
The original id
of an item is based on the current length of the array, so the id
and the index
of the item are identical. As soon as you delete an item from the start/middle of the items, the indexes of all items after no longer match the id
. Instead use the id
and not the index, whenever you wish to remove an item.
In addition, don't depend on the length of the array, since deleting an item, and then adding another one would cause two items to have the same id
. Use a uuid
library or the native Crypto.randomUUID():
const { useReducer, useRef } = React;
const reducer = (state, action) => {
switch (action.type) {
case "add":
return [
...state,
{
id: crypto.randomUUID(),
name: action.name
}
];
case "remove":
return state.filter(x => x.id !== action.id);
default:
return state;
}
}
function App() {
const inputRef = useRef();
const [items, dispatch] = useReducer(reducer, []);
function handleSubmit(e) {
e.preventDefault();
if (inputRef.current.value !== "") {
dispatch({
type: "add",
name: inputRef.current.value
});
}
inputRef.current.value = "";
}
return (
<div className="App">
<form onSubmit={handleSubmit}>
<input ref={inputRef} />
</form>
<ul>
{items.map(({ name, id }) => (
<li key={id}>
{name}
<button onClick={() => dispatch({ type: "remove", id })}>
X
</button>
</li>
))}
</ul>
</div>
);
}
ReactDOM
.createRoot(root)
.render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>