'리액트를 다루는 기술' 10장, 일정 관리 웹 애플리케이션 만들기

Jake_Young·2020년 8월 23일
0
post-thumbnail

😇 프로젝트 준비하기

TodoTemplate

  • 화면을 가운데 정렬 시켜주며 앱 타이틀을 보여준다.
  • childred 내부 jsx를 props로 받아 와서 렌더링 해준다

TodoInsert

  • 새로운 항목을 입력하고 추가할 수 있는 컴포넌트
  • state로 인풋의 상태를 관리한다.

TodoListItem

  • 각 할 일 항목에 대한 정보를 보여주는 컴포넌트.
  • todo 객체를 props로 받아 와서 상태에 따라 다른 스타일의 UI를 보여준다

TodoList

  • todos 배열을 props로 받아 온 후, map을 사용하여 여러 개의 TodoListItem으로 변환한다.

😎 UI 구성하기

Flexbox Froggy

  • flex 관련해서 공부하기

😱 기능 구현하기

  • 할 일 목록 만드는 기능을 구현한다
  • 할 일을 추가, 제거, 수정 할 수 있는 기능이 담겨 있다.

App

import React, { useState, useRef, useCallback } from 'react';
import TodoTemplate from './components/TodoTemplate';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';

const App = () => {
  const [todos, setTodos] = useState([
    {
      id: 1,
      text: 'the basic of react',
      checked: true,
    },
    {
      id: 2,
      text: 'the css of styling',
      checked: true,
    },
    {
      id: 3,
      text: 'the todos of myself',
      checked: false,
    },
  ]);

  const nextId = useRef(4);

  const onInsert = useCallback(
    (text) => {
      const todo = {
        id: nextId.current,
        text,
        checked: false,
      };
      setTodos(todos.concat(todo));
      nextId.current += 1;
    },
    [todos],
  );

  const onRemove = useCallback(
    (id) => {
      setTodos(todos.filter((todo) => todo.id !== id));
    },
    [todos],
  );

  const onToggle = useCallback(
    (id) => {
      setTodos(
        todos.map((todo) =>
          todo.id === id ? { ...todo, checked: !todo.checked } : todo,
        ),
      );
    },
    [todos],
  );

  return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert} />
      <TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
    </TodoTemplate>
  );
};

export default App;

TodoTemplate

import React from 'react';
import './TodoTemplate.scss';

export default function TodoTemplate({ children }) {
  return (
    <div className="TodoTemplate">
      <div className="app-title">Schedule Table</div>
      <div className="content">{children}</div>
    </div>
  );
}

TodoInsert

import React, { useState, useCallback } from 'react';
import { MdAdd } from 'react-icons/md';
import './TodoInsert.scss';

export default function TodoInsert({ onInsert }) {
  const [value, setValue] = useState('');

  const onChange = useCallback((e) => {
    setValue(e.target.value);
  }, []);

  const onSubmit = useCallback(
    (e) => {
      onInsert(value);
      setValue('');
      e.preventDefault();
    },
    [onInsert, value],
  );

  return (
    <form className="TodoInsert" onSubmit={onSubmit}>
      <input
        placeholder="what is your todo??"
        value={value}
        onChange={onChange}
      ></input>
      <button type="submit">
        <MdAdd></MdAdd>
      </button>
    </form>
  );
}

TodoList

import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';

export default function TodoList({ todos, onRemove, onToggle }) {
  return (
    <div className="TodoList">
      {todos.map((todo) => (
        <TodoListItem
          todo={todo}
          key={todo.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

TodoListItem

import React from 'react';
import {
  MdCheckBoxOutlineBlank,
  MdCheckBox,
  MdRemoveCircleOutline,
} from 'react-icons/md';
import './TodoListItem.scss';
import cn from 'classnames';

export default function TodoListItem({ todo, onRemove, onToggle }) {
  const { id, text, checked } = todo;
  return (
    <div className="TodoListItem">
      <div className={cn('checkbox', { checked })} onClick={() => onToggle(id)}>
        {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
        <div className="text">{text}</div>
      </div>
      <div className="remove" onClick={() => onRemove(id)}>
        <MdRemoveCircleOutline />
      </div>
    </div>
  );
}
profile
자바스크립트와 파이썬 그리고 컴퓨터와 네트워크

0개의 댓글