I have an incrementing key in my React To Do App so I can filter out certain tasks with an id identifier. For some reason, I have to declare and define my id outside of the main function. Why can't I declare and define it inside the main function? Will this affect my website during production since it's a component that gets exported to the main app?
import { useState } from "react";
//incrementing variable outside of main function
let nextId = 1;
//main function
const ToDoList = () => {
//I make an initial list with only one task so the list renders something at the start, obj in arr brackets
const initialList = [{ id: 0, taskName: "Example Task" }];
//set up useState for list and setlist as well as inputvalue and setinputvalue
const [list, setList] = useState(initialList);
const [inputValue, setInputValue] = useState<string>("");
//id increments with each add goal click, but incrementing variable has to be declared and defined outside main function
function handleAddClick() {
if (inputValue.length > 0) {
setList([...list, { id: nextId++, taskName: inputValue }]);
}
setInputValue("");
}
//delete tasks by rendering with filter method on ids
function handleDeleteClick(id) {
console.log(id);
setList([...list.filter((item) => item.id !== id)]);
}
return (
<>
<ul id="list">
{list.map((item) => {
return (
<>
<li key={item.id}>
<input type="checkbox" />
{item.taskName}
<span onClick={() =>
handleDeleteClick(item.id)}>❌
</span>
</li>
</>
);
})}
</ul>
<section>
<input
onKeyUp={(e) => {
if (e.key === "Enter") {
handleAddClick();
}
}}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
id="addGoal"
placeholder="Add a Goal here!">
</input>
<button onClick={handleAddClick}>Add Goal!</button>
<textarea placeholder="Here's some space to use as a place to type your
thoughts!">
</textarea>
</section>
</>
);
};
export default ToDoList;
This isn't as important, but I also don't understand why I get a lint error on line 23, column 29 from TypeScript saying "Parameter 'id' implicitly has an 'any' type. It's the function handleAddClick that has the id argument that gets the error. I try to say it's a number, but it doesn't work. I know it's getting a property from an object which is a number, but I don't know how to write the typing.
Here is what the code should look like with a ListType interface
import { useState } from "react";
//incrementing variable outside of main function
let nextId = 1;
interface ListType {
id: number;
taskName: string;
}
//main function
const ToDoList = () => {
//I make an initial list with only one task so the list renders something at the start, obj in arr brackets
const initialList: ListType[] = [{ id: 0, taskName: "Example Task" }];
//set up useState for list and setlist as well as inputvalue and setinputvalue
const [list, setList] = useState<ListType[]>(initialList);
const [inputValue, setInputValue] = useState<string>("");
//id increments with each add goal click, but incrementing variable has to be declared and defined outside main function
function handleAddClick() {
if (inputValue.length > 0) {
setList([...list, { id: nextId++, taskName: inputValue }]);
}
setInputValue("");
}
//delete tasks by rendering with filter method on ids
function handleDeleteClick(id: number) {
console.log(id);
setList([...list.filter((item) => item.id !== id)]);
}
return (
<>
<ul id="list">
{list.map((item: ListType) => {
return (
<>
<li key={item.id}>
<input type="checkbox" />
{item.taskName}
<span onClick={() =>
handleDeleteClick(item.id)}>❌
</span>
</li>
</>
);
})}
</ul>
<section>
<input
onKeyUp={(e) => {
if (e.key === "Enter") {
handleAddClick();
}
}}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
id="addGoal"
placeholder="Add a Goal here!">
</input>
<button onClick={handleAddClick}>Add Goal!</button>
<textarea placeholder="Here's some space to use as a place to type your
thoughts!">
</textarea>
</section>
</>
);
};
export default ToDoList;
Now I don't know how you handle your nextId but that would be another issue if that doesn't work.