10장 일정 관리 웹 애플리케이션 만들기


참조하려는 컴포넌트 창이 열러있지 않으면 import 자동으로 못해줌
→ jsconfig.json 만들어줘서 setting해줌

{
  "compilerOptions": {
    "target": "es2020"
  }
}

해주면 창 닫혀있어도 자동 import 된다.

일정관리 웹 애플리케이션 만들기

TodoListItem이 각 할일 마다의 컴포넌트를 작성해주고 TodoList 가 TodoListItem 들을 이용해서 List를 출력한다.
TodoInsert 는 입력 수행
App에서 Todo와 함수들을 관리하고 props로 TodoList 에 넘겨준다.

const App = () => {
  const [todos, setTodos] = useState([
    {
      id: 1,
      text: "리액트의 기초 알아보기",
      checked: true,
    },
    {
      id: 2,
      text: "컴포넌트 스타일링 해보기",
      checked: true,
    },
    {
      id: 3,
      text: "일정 관리 앱 만들어 보기",
      checked: false,
    },
  ]);

  const nextId = useRef(4);
  const onInsert = useCallback(
    (text) => {
      setTodos([...todos, { id: nextId.current, text: text, cehcked: false }]);
      nextId.current += 1;
    },
    [todos]
  );
  const onDelete = useCallback(
    (id) => {
      const newTodos = todos.filter((todo) => todo.id != id);
      setTodos(newTodos);
    },
    [todos]
  );
  const onToggle = useCallback((id) => {
    setTodos(
      todos.map((todo) =>
        id == todo.id ? { ...todo, checked: !todo.checked } : todo
      )
    );
  });
  return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert} />
      <TodoList todos={todos} onDelete={onDelete} onToggle={onToggle} />
    </TodoTemplate>
  );
};

export default App;
const TodoInsert = ({ onInsert }) => {
  const [value, setValue] = useState("");
  const onChange = useCallback((e) => {
    setValue(e.target.value);
  }, []);
  const onSubmit = useCallback(
    (e) => {
      onInsert(value);
      setValue("");

      //submit 이벤트는 브라우저에서 새로고침을 발생시킴
      // 이를 방지하기 위한 함수호출
      e.preventDefault();
    },
    [onInsert, value]
  );
  return (
    <form className="TodoInsert" onSubmit={onSubmit}>
      <input
        value={value}
        placeholder="할 일을 입력하세요"
        onChange={onChange}
      />
      <button type="submit">
        <MdAdd />
      </button>
    </form>
  );
};
const TodoList = ({ todos, onDelete, onToggle }) => {
  const todosList = todos.map((todo) => (
    <TodoListItem
      todo={todo}
      key={todo.key}
      onDelete={onDelete}
      onToggle={onToggle}
    />
  ));
  return <div className="TodoList">{todosList}</div>;
};
const TodoListItem = ({ todo, onDelete, onToggle }) => {
  const { id, text, checked } = todo;
  return (
    <div className="TodoListItem">
      <div className={cn("checkbox", { checked })} onClick={() => onToggle(id)}>
        {/* `checkbox ${checked ? "checked" : ""}` */}
        {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
        <div className="text">{text}</div>
      </div>
      <div className="remove" onClick={() => onDelete(id)}>
        <MdRemoveCircleOutline />
      </div>
    </div>
  );
};