I'm trying to make an obligatory Todo app to help with my React learning . The behavior I'm going for is multiple Todo lists, where you select a todo name and the list of todo items for that show. Select a different todo name and it's list todo items show, etc (like wunderlist/msft todo). For now it's using static json where each item has a child array.
I'm trying to check/uncheck a checkbox in order to mark the todo as done. My problem is that when a click the checkbox it doesn't update until a click away and then click back. What do I need to do to get it to update immediately?
code sandbox: https://codesandbox.io/s/github/cdubone/todo-react-bootstrap?file=/src/App.js
Here's the relevant code:
The function:
const updateChecked = todo => {
todo.IsChecked = !todo.IsChecked;
};
Properties on the component:
onChange={() => updateChecked(todo)}
isChecked={todo.IsChecked}
The input in the component:
<input
type="checkbox"
id={props.id}
name={props.id}
value={props.title}
checked={props.isChecked}
onChange={props.onChange}
/>
Here's the rest of the code if this helps -
JSON:
const TodoData = [
{
"Id": 1,
"Title": "Groceries",
"TodoList": [
{
"Id": 1,
"Title": "Apples",
"IsChecked": false
},
{
"Id": 2,
"Title": "Oranges",
"IsChecked": false
},
{
"Id": 3,
"Title": "Bananas",
"IsChecked": true
}
]
},
{
"Id": 2,
"Title": "Daily Tasks",
"TodoList": [{
"Id": 11,
"Title": "Clean Kitchen",
"IsChecked": false
},
{
"Id": 12,
"Title": "Feed Pets",
"IsChecked": false
},
{
"Id": 13,
"Title": "Do Stuff",
"IsChecked": false
}]
},
{
"Id": 3,
"Title": "Hardware Store",
"TodoList": []
},
{
"Id": 4,
"Title": "Costco",
"TodoList": [{
"Id": 21,
"Title": "Diapers",
"IsChecked": false
},
{
"Id": 22,
"Title": "Cat Food",
"IsChecked": false
},
{
"Id": 23,
"Title": "Apples",
"IsChecked": false
},
{
"Id": 24,
"Title": "Bananas",
"IsChecked": false
}]
},
{
"Id": 5,
"Title": "Work",
"TodoList": [
{
"Id": 34,
"Title": "TPS Reports",
"IsChecked": true
}
]
}
]
export default TodoData;
App.js
function App() {
const [todoData, setTodoData] = useState([]);
const [activeTodoList, setActiveTodoList] = useState(null);
const [todoListFormValue, setTodoListFormValue] = useState('');
const [todoListEditorToOpen, setTodoListEditorToOpen] = useState('');
const [todoListToAdd, setTodoListToAdd] = useState('');
const [todoItemToAdd, setTodoItemToAdd] = useState('');
useEffect(() => {
setTodoData(TodoData);
setActiveTodoList(TodoData[0]);
}, []);
const addTodoList = e => {
e.preventDefault();
const newItem = {
"Id": randomNumber(),
"Title": todoListToAdd,
"TodoList": []
};
const newArray = [...todoData, newItem];
setTodoData(newArray);
setActiveTodoList(newItem);
setTodoListToAdd('');
};
const deleteTodoList = (todolist) => {
const newArray = todoData.filter(x => x !== todolist);
setTodoData(newArray);
setActiveTodoList(newArray[0]);
};
const saveEditTodoListTitle = (e) => {
e.preventDefault();
const id = Number(e.currentTarget.dataset.id);
const result = todoData.find(x => x.Id === id);
result.Title = todoListFormValue;
closeTodoListTitleEditor();
};
const openTodoListTitleEditor = (todo) => {
setTodoListEditorToOpen(todo.Id);
setTodoListFormValue(todo.Title);
};
const closeTodoListTitleEditor = () => {
setTodoListEditorToOpen('');
};
const addTodoHandler = e => {
e.preventDefault();
const newItem = {
"Id": randomNumber(),
"Title": todoItemToAdd,
"IsChecked": false
};
const newArray = [...activeTodoList.TodoList, newItem];
activeTodoList.TodoList = newArray;
setTodoItemToAdd('');
};
const updateChecked = todo => {
todo.IsChecked = !todo.IsChecked;
};
const deleteTodo = (todo) => {
const newArray = activeTodoList.TodoList.filter(x => x !== todo);
console.log(newArray);
activeTodoList.TodoList = newArray;
setActiveTodoList(activeTodoList);
};
const randomNumber = () => {
return Math.floor(Math.random() * 200) + 100;
};
const updateEditTodoList = e => {
setTodoListFormValue(e.target.value);
}
const updateAddList = e => {
setTodoListToAdd(e.target.value);
};
const updateAddTodo = e => {
setTodoItemToAdd(e.target.value);
};
return (
<div className="App">
<div className="container">
<Header />
<div className="row">
<ul className="list-group col-sm-4 offset-sm-1">
{todoData.map(todo => (
<TodoListItem key={todo.Id}//Not a prop
onClick={() => setActiveTodoList(todo)}
title={todo.Title}
length={todo.TodoList.length}
selected={activeTodoList.Id === todo.Id}
deleteClick={() => deleteTodoList(todo)}
editClick={() => openTodoListTitleEditor(todo)}
saveEdit={saveEditTodoListTitle}
closeEditClick={() => closeTodoListTitleEditor()}
editorOpen={todoListEditorToOpen === todo.Id}
updateForm={updateEditTodoList}
value={todoListFormValue}
id={todo.Id} />
))}
<TextInput
onSubmit={addTodoList}
placeholder="Add New List"
value={todoListToAdd}
onChange={updateAddList} />
</ul>
<div className="col-sm-6">
{activeTodoList && (
<ul className="list-group">
<h2>{activeTodoList.Title} List</h2>
{activeTodoList.TodoList.map(todo => (
<TodoItem key={todo.Id} //not a prop
id={todo.Id}
title={todo.Title}
onChange={() => updateChecked(todo)}
isChecked={todo.IsChecked}
deleteClick={() => deleteTodo(todo)} />
))}
</ul>
)}
<TextInput
onSubmit={addTodoHandler}
placeholder="Add New Todo"
value={todoItemToAdd}
onChange={updateAddTodo} />
</div>
</div>
</div>
</div>
);
}
export default App;
TodoItem.js
import React from 'react';
import { PencilIcon, XIcon } from '@primer/octicons-react';
// import PropTypes from "prop-types";
function TodoItem(props) {
let wrapperClass = "list-group-item list-group-item-action todo-item";
if (props.isChecked === true) {
wrapperClass += " done";
}
return (
<li className={wrapperClass}>
<input
type="checkbox"
id={props.id}
name={props.id}
value={props.title}
checked={props.isChecked}
onChange={props.onChange}
/>
<label htmlFor={props.id}>{props.title}</label>
<div className='modify-todo'>
<button><PencilIcon size={16} /></button>
<button data-parent={props.id} onClick={props.deleteClick}><XIcon size={16} /></button>
</div>
</ li>
)
}
export default TodoItem;
Aucun commentaire:
Enregistrer un commentaire