TIL - 221005

연주·2022년 10월 7일
0

KDT-TIL

목록 보기
24/36

22.10.05 수요일

📝To-do-list 기능 구현

✏️ App에서 todos 상태 사용하기

app.js

 const [todos, setTodos] = useState([
    {
      id: 1,
      text: '리액트의 기초 알아보기',
      checked: true,
    },
    {
      id: 2,
      text: '컴포넌트 스타일링 해보기',
      checked: true,
    },
    {
      id: 3,
      text: '일정 관리 앱 만들어 보기',
      checked: false,
    },
  ]);
  // 일정을 배열에 담아주었다.
  
  
{/* todos를 TodoList에서 쓰기위해 porps로 전달 */}
 <TodoList todos={todos}></TodoList>

  

TodoList.js

// 부모 컴포넌트에서 받은 todos를 사용
const TodoList = ({ todos }) => {
  return (
    <TodoListBox>
      {todos.map((todo) => (
        <TodoListItem todo={todo} key={todo.id} />
        // props로 받아온 todos를 map함수를 이용해서 TodoListItem 으로 보내준다.
        // 객체를 통재로 props로 전달
      ))}
  • map을 사용하여 컴포넌트를 변환할때는 key props를 전달
    -> key값으로 todo.id를 넣었고,
    todo데이터를 통째로 props로 전달

TodoListItem.js

import cn from 'classnames';
: 조건부 스타일링을 위해 classname이라는 것을 사용한다.

const TodoListItem = ({ todo }) => {
  const { text, checked } = todo;
  // todo의 text와 checked값을 구조분해할당해서 가져와서 사용
  return (
    <TodoListItemBox>
      <div className={cn('checkbox', { checked })}>
        {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
        {/* checked가 참이면 참 값을 , 거짓이면 거짓값을 보여준다. */}
        <div>{text}</div>
      </div>
      <div>
        <MdRemoveCircleOutline />
      </div>
    </TodoListItemBox>
  );
};


✏️ 항목 추가 기능 구현하기

TodoInsert.js
value로 상태관리 하기

const TodoInsert = () => {
  const [value, setValue] = useState('');
  // input에 입력하는 값을 관리하는 value를 만들어주었다
  const onChange = useCallback((e) => {
    setValue(e.target.value);
  }, []);
  // 추가로 input에 넣어줄 함수를 만들어줌
  // usecallback -> 컴포넌트가 리렌더링될때마다 함수를 새로 만드는 것이 아니라
  // 한 번 함수를 만들고 재사용할 수 있게해준다.
  return (
    <Formbox>
      <input
        placeholder="할 일을 입력하세요"
        value={value}
        onChange={onChange}
      ></input>
      {/* value값과 onchange함수를 주었다. */}
      <button type="sumit">
        <MdAdd />
      </button>
    </Formbox>
  );
};

export default TodoInsert;

✏️ todo배열에 새 객체 추가하기

App.js

  const nextId = useRef(4);
  // 객체가 새로 생겨서 새로 id 값이 필요하니끼
  // ref를 사용하여 변수를 담았다.
  // usestate가 아니라 useRef담은 것은
  // id값은 렌더링되는 정보가 아니기 때문

  // 함수의 성능을 아낄 수 있도록, useCallback으로 감싸주었다.
  const onInsert = useCallback(
    (text) => {
      const todo = {
        id: nextId.current,
        text,
        checked: false,
      };
      setTodos(todos.concat(todo));
      nextId.current += 1;
    },
    [todos],
  );
  return (
    <MainBox>
      <TodoTemplate>
        <TodoInsert onInsert={onInsert}></TodoInsert>
        {/* onInsert함수를 TodoInsert에서 사용하기위해 porps로 전달 */}
        <TodoList todos={todos}></TodoList>
        {/* todos를 TodoList에서 쓰기위해 porps로 전달 */}
      </TodoTemplate>
    </MainBox>
  );
}

export default App;

✏️ TodoInsert에서 onSubmit 이벤트 설정하기

버튼을 클릭하면 이벤트가 발생하도록한다.
App.js에서 받아온 onInsert함수를 value값에 파라미터로 넣어 호출

TodoInsert.js

const TodoInsert = ({ onInsert }) => {
  const [value, setValue] = useState('');
  // input에 입력하는 값을 관리하는 value를 만들어주었다
  const onChange = useCallback((e) => {
    setValue(e.target.value);
  }, []);
  // 추가로 input에 넣어줄 함수를 만들어줌
  // usecallback -> 컴포넌트가 리렌더링될때마다 함수를 새로 만드는 것이 아니라
  // 한 번 함수를 만들고 재사용할 수 있게해준다.

  const onSubmit = useCallback(
    (e) => {
      onInsert(value);
      setValue(''); // value 값 초기화
      // form의 submit 버튼을 눌렀을때 새로고침 이 발생하니까
      // 그래서 방지하기 위해 아래 함수를 호출
      e.preventDefault();
    },
    [onInsert, value],
  );

  return (
    <Formbox onSubmit={onSubmit}>
      <input
        placeholder="할 일을 입력하세요"
        value={value}
        onChange={onChange}
      ></input>
      {/* value값과 onchange함수를 주었다. */}
      {/* input에 입력된 값이 onInsert함수에 의해
      배열에 새로운 객체로 들어가고, 들어가게 되면 setValue로
      input창이 빈칸이 된다. */}
      <button type="submit">
        {/* submit는 버튼+enter키로도 작동하고, click 이벤트는
        클릭 할때만 작동한다. */}
        <MdAdd />
      </button>
    </Formbox>
  );
};

export default TodoInsert;

✏️ 지우기 기능 구현 하기

App.js

const onRemove = useCallback((id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  },[todos]);
  return (
    <MainBox>
      <TodoTemplate>
        <TodoInsert onInsert={onInsert}></TodoInsert>
        {/* onInsert함수를 TodoInsert에서 사용하기위해 porps로 전달 */}
        <TodoList todos={todos} onRemove={onRemove}></TodoList>
        {/* todos를 TodoList에서 쓰기위해 porps로 전달 */}
        {/* onInsert함수를 TodoListItem에서 사용하기 위해 일단 TodoLIst로 porps로 전달 */}
      </TodoTemplate>
    </MainBox>
  );
}

TodoList.js
우리가 써야할 곳은 TodoListItem이기 때문에 한번 더 props로 내려준다.

const TodoList = ({ todos , onRemove}) => {
  return (
    <TodoListBox>
      {todos.map((todo) => (
        <TodoListItem todo={todo} key={todo.id} onRemove={onRemove} />
        // props로 받아온 todos를 map함수를 이용해서 TodoListItem 으로 보내준다.
        // 객체를 통재로 props로 전달
      ))}
      
    </TodoListBox>
  );
};

TodoListItem.js

const TodoListItem = ({ todo, onRemove }) => {
  const { id, text, checked } = todo;
  // todo의 text와 checked값을 구조분해할당해서 가져와서 사용
  // onRemove함수에서 id값이 필요하니까 또 가져와서 사용한다.
  return (
    <TodoListItemBox>
      <div className={cn('checkbox', { checked })}>
        {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
        {/* checked가 참이면 참 값을 , 거짓이면 거짓값을 보여준다. */}
        <div>{text}</div>
      </div>
      <div
        onClick={() => {
          onRemove(id);
        }}
      >
        {/*   const onRemove = useCallback((id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  },[todos]); 
  
  클릭을 하게 되면 id값이 인자로 들억사서 일치하게되어
  해당 클릭값부분만 삭제된다*/}
        <MdRemoveCircleOutline />
      </div>
    </TodoListItemBox>
  );
};

export default TodoListItem;

✏️ 수정기능 (할일을 끝냈으면 체크해서 지우는 것)

-삭제기능과 비슷

App.js

  const onToggle = useCallback(
    (id) => {
      setTodos(
        todos.map((todo) =>
          todo.id === id ? { ...todo, check: !todo.checked } : todo,
        ),
      );
    },
    [todos],
  );
  return (
    <MainBox>
      <TodoTemplate>
        <TodoInsert onInsert={onInsert}></TodoInsert>
        {/* onInsert함수를 TodoInsert에서 사용하기위해 porps로 전달 */}
        <TodoList todos={todos} onRemove={onRemove} onToggle={onToggle}></TodoList>
        {/* todos를 TodoList에서 쓰기위해 porps로 전달 */}
        {/* onInsert함수를 TodoList에서 사용하기 위해 porps로 전달 */}
        {/* onInsert함수와 똑같이 onToggle함수를 TodoList에서 사용하기 위해 porps로 전달 */}
      </TodoTemplate>
    </MainBox>
  );

Todolist.js

const TodoList = ({ todos, onRemove, onToggle }) => {
  return (
    <TodoListBox>
      {todos.map((todo) => (
        <TodoListItem
          todo={todo}
          key={todo.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
        // props로 받아온 todos를 map함수를 이용해서 TodoListItem 으로 보내준다.
        // 객체를 통째로 props로 전달
      ))}
    </TodoListBox>

TodoListItem.js

const TodoListItem = ({ todo, onRemove, onToggle }) => {
  const { id, text, checked } = todo;
  // todo의 text와 checked값을 구조분해할당해서 가져와서 사용
  // onRemove함수에서 id값이 필요하니까 또 가져와서 사용한다.
  return (
    <TodoListItemBox>
      <div className={cn('checkbox', { checked })} onClick={() => onToggle(id)}>
        {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
        {/* checked가 참이면 참 값을 , 거짓이면 거짓값을 보여준다. */}
        <div>{text}</div>
      </div>
      <div
        onClick={() => {
          onRemove(id);
        }}
      >
        {/*   const onRemove = useCallback((id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  },[todos]); 
  
  클릭을 하게 되면 id값이 인자로 들어가서 일치하게되어
  해당 클릭값부분만 제외하고 다시 새 배열로 받아온다. */}
        <MdRemoveCircleOutline />
      </div>
    </TodoListItemBox>
  );
};

export default TodoListItem;

💬 저번에 이해하지 못했던 부분을 이해하려고 다시 기능 구현까지 해보았다.
10.06 - 팀원에게 속성 과외를 받아 어느 정도 이해가 되었다.
이 내용을 바탕으로 장바구니 부분의 값을 받아올 수 있게 되었다.

profile
성장중인 개발자🫰

0개의 댓글