Заголовок и описание дела в todo листе выводятся отдельными запросами
Мне нужно написать todo-лист, чтобы у каждого todo был заголовок(title) и описание дела (about). todo сделан с базой данных на firebase. В отдельных input заполняется заголовок и описание дела. Но когда нажимаю кнопку добавить (Add) выгружается только заголовок(поле в todo для описания дела пустое). При повторном нажатии Add выгружается только описание дела(заголовок остается пустой). И получаются две todo вместо одного полноценного с заголовком и описанием. Прикрепляю ссылку на git-реппозиторий: https://github.com/Kohlenbaron28/todo
//App.js:
import AddToDo from './components/AddToDo';
import './App.css';
import React from 'react';
import Title from './components/Title';
import Todo from './components/Todo';
import {
collection,
query,
onSnapshot,
doc,
updateDoc,
deleteDoc,
} from "firebase/firestore";
import { db } from "./firebase";
function App() {
const [todos, setTodos] = React.useState([]);
React.useEffect(() => {
const q = query(collection(db, "todos"));
const unsub = onSnapshot(q, (querySnapshot) => {
let todosArray = [];
querySnapshot.forEach((doc) => {
todosArray.push({ ...doc.data(), id: doc.id });
});
setTodos(todosArray);
});
return () => unsub();
}, []);
const handleEdit = async (todo, title, about) => {
await updateDoc(doc(db, "todos", todo.id), { title: title, });
};
const toggleComplete = async (todo) => {
await updateDoc(doc(db, "todos", todo.id), { completed: !todo.completed });
};
const handleDelete = async (id) => {
await deleteDoc(doc(db, "todos", id));
};
return (
<div className="App">
<div>
<Title/>
</div>
<div>
<AddToDo/>
</div>
<div className='todo_container'>
{todos.map((todo) => (
<Todo
key={todo.id}
todo={todo}
toggleComplete={toggleComplete}
handleDelete={handleDelete}
handleEdit={handleEdit}
/>
))}
</div>
</div>
);
}
export default App;
//AddToDo.js
import React from "react";
import { db } from "../firebase";
import { collection, addDoc } from "firebase/firestore";
export default function AddTodo() {
const [title, setTitle] = React.useState("");
const [about, setAbout] = React.useState("");
const handleSubmit = async (e) => {
e.preventDefault();
if (title !== "") {
await addDoc(collection(db, "todos"), {
title,
completed: false,
});
setTitle("");
} else if (about !== "") {
await addDoc(collection(db, "todos"), {
about,
completed: false,
});
setAbout("");
}
};
return (
<form onSubmit={handleSubmit}>
<div className="input_container">
<input
type="text"
placeholder="Enter todo..."
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
placeholder="Enter about..."
value={about}
onChange={(e) => setAbout(e.target.value)}
/>
</div>
<div className="btn_container">
<button>Add</button>
</div>
</form>
);
}
//Todo.js
import React from "react";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
export default function Todo({ todo, toggleComplete, handleDelete, handleEdit,}) {
const [newTitle, setNewTitle] = React.useState(todo.title);
const [newAbout, setNewAbout] = React.useState(todo.about);
const handleChange = (e) => {
e.preventDefault();
if (todo.complete === true) {
setNewTitle(todo.title);
setNewAbout(todo.about);
} else {
todo.title = "";
todo.about = "";
setNewTitle(e.target.value);
setNewAbout(e.target.value);
}
};
return (
<div className="todo">
<input
style={{ textDecoration: todo.completed && "line-through" }}
type="text"
value={todo.title === "" ? newTitle : todo.title}
className="list"
onChange={handleChange}
/>
<input
style={{ textDecoration: todo.completed && "line-through" }}
type="text"
value={todo.about === "" ? newAbout : todo.about}
className="list"
onChange={handleChange}
/>
<div>
<button
className="button-complete"
onClick={() => toggleComplete(todo)}
>
<CheckCircleIcon id="i" />
</button>
<button
className="button-edit"
onClick={() => handleEdit(todo, newTitle)}
>
<EditIcon id="i" />
</button>
<button className="button-delete" onClick={() => handleDelete(todo.id)}>
<DeleteIcon id="i" />
</button>
</div>
</div>
);
}
Ответы (1 шт):
Автор решения: Yuriy Sidorov
→ Ссылка
const handleSubmit = async (e) => {
e.preventDefault();
if (title !== "" || about !== "") {
await addDoc(collection(db, "todos"), {
title,
about,
completed: false,
});
setTitle("");
setAbout("");
}
};