[React] 투두리스트 컴포넌트 구조 및 코드 분석
// 리액트를 다루는 기술 10장
자바스크립트 코드는 책과 똑같고 scss는 굳이 쓰고 싶지 않아서 css만 사용했다
전체 코드는 깃헙에!
https://github.com/juhui88/ReactStudy/tree/master/todo-app/src
GitHub - juhui88/ReactStudy
Contribute to juhui88/ReactStudy development by creating an account on GitHub.
github.com
투두리스트 컴포넌트 구조
원래는 직접 만들어 보려고 했는데 파일이 여러개가 되다보니 머리가 복잡해져서.... 책을 따라하면서 배웠다.
새로 만들 기능들은 나중에 추가해볼 예정!
일단 컴포넌트는 크게
- App
- TodoTemplate
- TodoInsert
- TodoList
- TodoListItem
으로 나뉜다. 각자 어떤 props를 넘겨받는지를 아래에 조직화 해보았다.
TodoTemplate의 children이 TodoInsert와 TodoList로 설정된다.
App에서 todos 상태와 onRemove, onInsert, onToggle함수를 지니게 되고 해당 값들을 props를 사용해서 자식 컴포넌트로 전달해준다.
cn이 뭐지❓
다른 건 기능적으로 설명해주는데
import cn from {classnames};에 대해선 별 설명이 없어서 정리해보려고 한다.
classnames는 리액트 라이브러리 중 하나로 조건부로 classNames를 결합할 수 있는 자바스크립트의 유틸리티다.
그냥 import하면 안 되고 터미널에서 다음과 같이 추가적인 명령어를 실행시켜주어야 사용할 수 있다.
//npm
npm install classnames
//yarn
yarn add classnames
투두리스트 코드에 사용된 예시를 보자면
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline,
} from 'react-icons/md';
import './TodoListItem.css';
import cn from 'classnames';
const 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>
);
};
export default TodoListItem;
위와 같이 사용한다.
여기선 checkbox라는 이름은 미리 지정되어 있는 상태이고 todo의 한 요소인 checked라는 값이 true면 className에 checked가 추가되고 false라면 추가되지 않는다.
아래 추가적 예시를 통해 더 자세히 이해해보자!
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
// lots of arguments of various types
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
// other falsy values are just ignored
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
출처 : https://www.npmjs.com/package/classnames
즉, cn을 통해 조건부로 여러 개의 className을 사용할 수 있다!!