'Encountring very fundamental problem with react, why item.id in my case is increasing by +2?
hi i have just started learning react and facing problems in understanding fundamentals , here i am creating basic todo app question is why item-id in seq of 1,3,5,7.... as show in image attached How do i slove this ?
import { useState } from "react";
import "./App.css";
let counter = 0;
function App() {
const [text, setText] = useState("");
const [todos, setTodos] = useState([]);
const createTodo = (e) => {
e.preventDefault();
setText('')
setTodos((oldTodos) => [...oldTodos, { todo: text, id: counter++ }]);
};
return (
<div className="App">
<form onSubmit={createTodo}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
></input>
<button type="submit">Add Todo</button>
</form>
<ul>
{todos.map((item) => {
return (
<li key={item.id}>
{item.todo}-{item.id}
</li>
);
})}
</ul>
</div>
);
}
export default App;
browser output
[
Any better approach to slove issue??
Solution 1:[1]
try this code instead
const [text, setText] = useState("");
const [todos, setTodos] = useState([]);
const [count , setCount] = useState(0);
const createTodo = (e) => {
e.preventDefault();
setCount(count++)
setText('')
setTodos((oldTodos) => [...oldTodos, { todo: text, id: count }]);
};
Solution 2:[2]
Answer: getting rid of StrictMode
mode, you will produce the desired output.
But why?
With StrictMode:
const [text, setText] = useState("");
const [todos, setTodos] = useState([]);
console.log("Renders!"); // Add logging to see what happens
console.log(todos);
On page load, console shows:
Renders!
[]
Renders!
[]
the page reders twice, which is expected, and now we submit a string value one
, and the console shows:
Renders! // First render
[{todo: "one", id: 0}]
Renders! // Second render
[{todo: "one", id: 1}] // notice id value
From output, we can see the id of first todo item is already at 1, and it should've been zero, the starting value of counter
. That's because the setter invoked twice, as the page renders twice:
setTodos((oldTodos) => [...oldTodos, { todo: text, id: counter++ }]);
Without StrictMode:
Renders!
[{todo: "one", id: 0}]
Only renders once, and id is the starting point 0.
Sandbox here and for learning material recommend react beta docs
Solution 3:[3]
counter++
means you are re-assigning the value of the counter variable. counter = counter +1
, counter += 1
are alternatives for it. So what you can try is you can first change the value of the variable and then assign it to the id property.
let counter = 0;
function App(){
const [text, setText] = useState("");
const [todos, setTodos] = useState([]);
const createTodo = (e) => {
e.preventDefault();
setText('');
counter++; // or counter += value or counter = counter + value;
setTodos((oldTodos) => [...oldTodos, { todo: text, id: counter }]);
};
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Eisa Rezaei |
Solution 2 | |
Solution 3 | Shakya Peiris |