Appending a div in React using React hooks
I'm learning react at the moment and currently, making a todo app so that I can understand react more easily. So here's what I'm trying to do:
- The user clicks a button
- The click fires a prompt which asks the user for the todo title (only title at the moment)
- Then, that title is added to an array of all todos
- And then, use that array to display each todo on the page
Code:
const [check, setCheck] = useState(false);
const [todo, setTodo] = useState([]);
function handleClick() {
let toAdd = prompt('Title: ')
setTodo([...todo, {
title: toAdd
}]);
}
useEffect(()=> {
if(todo.length !== 0) {
setCheck(true);
}
})
return (
<div className="wholeContainer">
<div className="tododiv">
<span className="todos">Todos: </span>
<hr/>
{
check ?
todo.forEach((eachTodo)=> {
<TodoItems title={eachTodo}/>
})
: <span>Nothing</span>
}
</div>
<button className="add" onClick={handleClick}>
<i className="fas fa-plus"></i>
Add a Todo
</button>
</div>
);
The const [check, setCheck] = useState(false);
is written so that I can access the array if todo.length !== 0
;
The problem comes in the rendering part. I can't figure out a way to display each and every todo in their own <TodoItems/>
component, and also when using forEach()
, nothing happens because I think that someone told me that setState()
works asynchronously.
I really need some advice!
Thanks...
You are using
todo.forEach((eachTodo)=> {
<TodoItems title={eachTodo}/>
})
When you should be using
todo.map((eachTodo)=> {
return <TodoItems title={eachTodo}/>
})
Or
todo.map((eachTodo)=> (
<TodoItems title={eachTodo}/>
))
Also you have an infinite loop in your component:
useEffect(()=> {
if(todo.length !== 0) {
setCheck(true);
}
})
Each time the component updates, when the todo list isn't empty, you setCheck to true which triggers a new render. Also, you don't need to use state for every variable, only the ones were a change should trigger a re-render.
Also your new todo-list state depends on the previous state so you should use a functional update.
https://reactjs.org/docs/hooks-reference.html
const [todoList, setTodoList] = useState([]);
function handleClick() {
let toAdd = prompt('Title: ');
setTodoList((prevTodoList) => [...prevTodoList, toAdd]);
}
const isTodoListEmpty = todoList.length === 0
return (
<div className="wholeContainer">
<div className="tododiv">
<span className="todos">Todos: </span>
<hr />
{!isTodoListEmpty ? (
todoList.forEach((todoItem) => {
<TodoItems title={todoItem} />;
})
) : (
<span>Nothing</span>
)}
</div>
<button className="add" onClick={handleClick}>
<i className="fas fa-plus"></i>
Add a Todo
</button>
</div>
);