Reputation: 383
I am trying to create a to-do application in React. Code I have so far adds to-do items to the to-do list. When I click on the edit icon I had put turnery condition for the done icon but it's not working. Can someone explain what is wrong with my code?
App.js
import './App.css';
import React, { useState } from 'react';
import TodoList from './TodoList';
import { v4 as uuidv4 } from 'uuid';
function App() {
// const [input, setInput] = useState('');
const [todos, setTodo] = useState([]);
const input = React.useRef();
const addTodo = (e) => {
e.preventDefault();
const id = uuidv4();
setTodo([...todos, { id: id, text: input.current.value }])
input.current.value='';
}
const deleteTodo = (id) => {
setTodo(todos.filter(todo => todo.id !== id));
}
const editTodo = (id) => {
}
return (
<div className="App">
<form>
<input type="text" ref={input}/>
<button type="submit" onClick={addTodo}>Enter</button>
</form>
<TodoList todos={todos} deleteTodo={deleteTodo} editTodo={editTodo}/>
</div>
);
}
export default App;
TodoItem.js
import React from 'react'
import DeleteIcon from '@material-ui/icons/Delete';
import EditIcon from '@material-ui/icons/Edit';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import DoneIcon from '@material-ui/icons/Done';
const TodoItem = ({todo, deleteTodo, editTodo}) => {
return (
<>
<div>
<CheckBoxOutlineBlankIcon/>
<input type="text" value={todo.text} readOnly={true}/>
</div>
<div>
{ <EditIcon/> ? <EditIcon onClick={editTodo}/> : <DoneIcon/> }
<DeleteIcon onClick={deleteTodo}/>
</div>
</>
)
}
export default TodoItem
Upvotes: 0
Views: 1366
Reputation: 7935
There are a few problems with your code. One, also pointed out by Abu Sufian is that your ternary operator will always trigger whatever is immediately after ?
, because <EditIcon/>
is just a component and will always be true.
But more fundamentally, to do what you want, you will need to add another properly to your todo list, say, status
. So when a task goes in for the first time, it will be in pending
status, then once you click your Edit icon, it will change to done
. And that's how we will toggle that icon with a ternary operator.
So I would change your addTodo
function to
const addTodo = (e) => {
e.preventDefault();
const id = uuidv4();
setTodo([
...todos,
{ id: id, text: input.current.value, status: "pending" }
]);
input.current.value = "";
};
Then I would change your editTodo
to:
const editTodo = (id) => {
console.log(id);
setTodo(
todos.map((todo) => {
if (todo.id === id) todo.status = "done";
return todo;
})
);
};
And finally, I would change your ternary part to:
{todo.status === "pending" ? (
<EditIcon onClick={() => editTodo(todo.id)} />
) : (
<DoneIcon />
)}
Here is a complete Sandbox for you. Sorry I don't have your CSS so I can't make it look super pretty.
Upvotes: 1
Reputation: 1349
Maybe you are looking for something like this.
{ !todo.done ? <EditIcon onClick={editTodo}/> : <DoneIcon/> }
I believe checking whether a todo item is done or not should happen with a property of todo
object itself.
In a ternary you need to start with a condition.
condition ? do something when true : do something when false
So you have to have a condition in the first place. In your case EditIcon
is not a condition.
If you are looking for a way to mark a todo as completed so you need to do more things.
const markAsCompleted = id => {
const todo = todos.find(todo => todo.id !== id);
setTodo([...todos, {...todo, done: true }]);
}
Then you can decide based on whether a todo is done or not.
Upvotes: 1