App.js

import React, { useState, useEffect } from 'react';
import useFetch from './useFetch';
import List from './List';
import Header from './Header';

const App = () => {
	const [input, setInput] = useState('');
	const [todos, setTodos] = useState([]);

	const pending = useFetch(setTodos, '<https://koreanjson.com/todos>');

	useEffect(() => {
		setInput('');
	}, [todos]);

	const changeTodoCompleted = (id) => {
		const newTodos = todos.map(todo => todo.id === id ? {...todo, completed: !todo.completed} : todo);
		setTodos(newTodos);
	};

	return (
		<div>
			<Header todos={todos} />

			<form action="">
				<input type="text" name="" value={input} onChange={(e) => setInput(e.target.value)} />
				<button
					type="button"
					onClick={() => setTodos([...todos, {
						id: todos.length + 1,
						title: input,
						completed: false,
					}])}
				>
					할일추가
				</button>
			</form>

			{pending
				? 'loading...'
				: <List todos={todos} changeTodoCompleted={changeTodoCompleted} />
			}
		</div>
	);
};

export default App;

Header.js

import React from 'react';

const Header = ({ todos }) => {
	return (
		<div>
			<h1>hello todo application</h1>
			<div>해야할 일 : {todos.length}개가 있습니다.</div>
		</div>
	);
};

export default Header;

List.js

import React from 'react';
import Item from "./Item";

const List = ({ todos, changeTodoCompleted }) => {
	return (
		<ul>
			{todos.map(todo => (
				<Item key={todo.id} todo={todo} changeTodoCompleted={changeTodoCompleted} />
			))}
		</ul>
	);
};

export default List;

Item.js

import React from 'react';

const Item = ({ todo, changeTodoCompleted }) => {
	return (
		<li onClick={() => changeTodoCompleted(todo.id)} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.title}</li>
	);
};

export default Item;