Я создал свой первый проект на Реакте с запросами на сервер. Оцените пожалуйста, может есть какие-то недочеты, чего-то не хватает или что-то лишнее, или вообще есть более легкий способ реализации. Буду рад пообщаться.
App.js
import { useState } from 'react'
import Todoform from './Components/TodoForm'
function App() {
const [todo, setTodo] = useState([])
const todoLength = (todos) => {
if (todos) {
setTodo(todos)
}
}
return (
<div className="App">
<header>
<h1>Список задач: {todo.length} </h1>
</header>
<Todoform todoLength={todoLength} />
</div>
);
}
export default App;
Компонент TodoForm.js
import { useState, useEffect } from 'react'
import ModalInput from './ModalInput';
function Todoform({ todoLength }) {
const [modalActive, setModalActive] = useState(false)
const [error, setError] = useState(null)
const [isLoaded, setIsLoaded] = useState(false)
const [todos, setTodos] = useState([])
const [userInput, setUserInput] = useState('')
const [userInputUpdate, setUserInputUpdate] = useState('')
const [todo, setTodo] = useState([])
const [isChecked, setIsChecked] = useState(false);
const handleOnChange = () => {
setIsChecked(!isChecked);
};
useEffect(() => {
getTodos()
}, [])
const getTodos = () => {
fetch('http://localhost:3001/api/todo', {
method: 'GET',
})
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setTodos(result);
todoLength(result)
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}
const createTodo = () => {
fetch('http://localhost:3001/api/todo', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
todo_text: userInput,
complete: false
}),
})
.then((res) => res.json())
.then(result => {
setTodos([...todos, result])
getTodos()
},
(error) => {
setIsLoaded(true)
setError(error)
}
)
}
const updateTodo = (id, todo_text, complete) => {
fetch(`http://localhost:3001/api/todo`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
todo_text: todo_text,
complete: complete,
id: id
}),
})
.then((res) => res.json())
.then(result => {
setTodos([...todos])
getTodos()
},
(error) => {
setIsLoaded(true)
setError(error)
}
)
}
const removeTodo = (id) => {
fetch(`http://localhost:3001/api/todo/${id}`, {
method: 'DELETE',
})
.then(data => {
// alert(data)
getTodos()
})
}
const handleChange = (e) => {
setUserInput(e.currentTarget.value)
}
const handleSubmit = (e) => {
e.preventDefault()
if (userInput) {
setUserInput('')
createTodo()
}
}
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
handleSubmit(e)
}
}
const handleModalChange = (e) => {
setUserInputUpdate(e.currentTarget.value)
}
const handleModalSubmit = (event) => {
event.preventDefault()
if (userInputUpdate) {
setUserInputUpdate('')
updateTodo(todo[0], userInputUpdate, isChecked)
setModalActive(false)
}
}
const handleKeyPressmodal = (e) => {
if (e.key === 'Enter') {
handleModalSubmit(e)
}
}
if (error) {
return <div>Ошибка: {error.message}</div>;
} else if (!isLoaded) {
return <div>Загрузка...</div>;
} else if (todos) {
return (
<div>
<form onSubmit={handleSubmit}>
<input
className='input'
value={userInput}
type="text"
onChange={handleChange}
onKeyDown={handleKeyPress}
placeholder="Введите текст"
/>
<button className="item-save">Сохранить</button>
</form>
{todos.map((todo) => {
return (<div className="todos" >
<div key={todo.id} className="item-todo" >
<div className={todo.complete ? "item-text strike" : "item-text"} >
{todo.todo_text} {todo.complete}
</div>
<div className='todo-checkbox'>
<input className='checkbox' type="checkbox" checked={todo.complete ? true : false} onChange={() => { updateTodo(todo.id, todo.todo_text, !todo.complete); setIsChecked(!todo.complete) }} />
</div>
</div>
<button className="item-update" onClick={() => { setModalActive(true); setTodo([todo.id, todo.todo_text, todo.complete]); setUserInputUpdate(todo.todo_text); setIsChecked(todo.complete) }}>
Изменить
</button>
<button className="item-delete" onClick={() => removeTodo(todo.id)}>
X
</button>
</div>)
})}
<ModalInput active={modalActive} setActive={setModalActive}>
<form onSubmit={handleModalSubmit}>
<input
className='input'
value={userInputUpdate}
type="text"
onChange={handleModalChange}
onKeyDown={handleKeyPressmodal}
placeholder="Введите текст"
/>
<input className='checkbox' type="checkbox" checked={isChecked ? true : false} onChange={handleOnChange} />
<button className="item-save">Сохранить</button>
</form>
</ModalInput>
</div>
)
}
}
export default Todoform
ModalInput.js
const ModalInput = ({ active, setActive, children }) => {
return (
<div className={active ? "modal active" : "modal"} onClick={() => setActive(false)}>
<div className={active ? "modal__content active" : "modal__content"} onClick={e => e.stopPropagation()}>
{children}
</div>
</div>
)
}
export default ModalInput
Ссылка на полный проект с серверной частью:
https://github.com/pandycrowl/Crud-ToDo-List.git
И у меня есть пару вопросов:
1. Я видел, что для файлов компонентов используют расширение .jsx, но jsx работает и с раcширением .js. Я что-то не понял или без разницы какое расширение?
2. Я не знаю как избавиться от двух предупреждений: 1)"Warning: Each child in a list should have a unique "key" prop. Check the render method of Todoform." 2) "React Hook useEffect has a missing dependency: 'getTodos'. Either include it or remove the dependency array react-hooks/exhaustive-deps"