728x90
반응형

ToDoItemList 컴포넌트 만들기

이 컴포넌트는 이후에 만들 ToDoItem 컴포넌트 여러개를 렌더링해주는 역할을 함

 

src/components/ToDoItemList.js

import React, { Component } from 'react';

class ToDoItemList extends Component {
  render() {
    const { todos, onToggle, onRemove } = this.props;

    return (
      <div>

      </div>
    );
  }
}

export default ToDoItemList;

이렇게 비어있는 컴포넌트를 생성

이 컴포넌트는 3가지의 props를 받게 됨

1️⃣ todos: todo 객체들이 들어있는 배열

2️⃣ onToggle: 체크박스를 키고 끄는 함수

3️⃣ onRemove: 아이템을 삭제시키는 함수

 

 

ToDoItem 컴포넌트 만들기

 

components 디렉토리에 다음 파일들을 생성

src/components/ToDoItem.js

src/components/ToDoItem.css

 

src/components/ToDoItem.js

import React, { Component } from 'react';
import './TodoItem.css';

class TodoItem extends Component {
  render() {
    const { text, checked, id, onToggle, onRemove } = this.props;

    return (
      <div className="todo-item" onClick={() => onToggle(id)}>
        <div className="remove" onClick={(e) => {
          e.stopPropagation(); // onToggle 이 실행되지 않도록 함
          onRemove(id)}
        }>&times;</div>
        <div className={`todo-text ${checked && 'checked'}`}>
          <div>{text}</div>
        </div>
        {
          checked && (<div className="check-mark">✓</div>)
        }
      </div>
    );
  }
}

export default TodoItem;

이 컴포넌트는 총 5가지의 porps를 전달받게 됨

1️⃣ text : todo 내용

2️⃣ checked : 체크박스 상태

3️⃣ id : todo의 고유 아이디

4️⃣ onToggle : 체크박스를 키고 끄는 함수

5️⃣ onRemove : 아이템을 삭제시키는 함수

 

해당 컴포넌트 최상위 DOM의 클릭 이벤트에는 onToggle을 넣어주고, x가 있는 부분에선 onRemove를 넣어줌

onRemove를 호출하는 곳을 보면 e.stopPropagation()이라는 것이 호출됨

e.stopPropagation() 은 이벤트의 “확산” 을 멈춰줌

즉, 삭제부분에 들어간 이벤트가 해당 부모의 이벤트까지 전달되지 않도록 해줌 👉 onToggle은 실행되지 않고 onRemove만 실행

 

 

src/components/ToDoItem.css

.todo-item {
  padding: 1rem;
  display: flex;
  align-items: center; /* 세로 가운데 정렬 */
  cursor: pointer;
  transition: all 0.15s;
  user-select: none;
}

.todo-item:hover {
  background: #e3fafc;
}

/* todo-item 에 마우스가 있을때만 .remove 보이기 */
.todo-item:hover .remove {
  opacity: 1;
}

/* todo-item 사이에 윗 테두리 */
.todo-item + .todo-item {
  border-top: 1px solid #f1f3f5;
}


.remove {
  margin-right: 1rem;
  color: #e64980;
  font-weight: 600;
  opacity: 0;
}

.todo-text {
  flex: 1; /* 체크, 엑스를 제외한 공간 다 채우기 */
  word-break: break-all;
}

.checked {
  text-decoration: line-through;
  color: #adb5bd;
}

.check-mark {
  font-size: 1.5rem;
  line-height: 1rem;
  margin-left: 1rem;
  color: #3bc9db;
  font-weight: 800;
}

 

이제 해당 컴포넌트를 ToDoItemList에서 불러와서 렌더링 해보기

src/components/ToDoItemList.js

import React, { Component } from 'react';
import ToDoItem from './ToDoItem';

class ToDoItemList extends Component {
  render() {
    const { todos, onToggle, onRemove } = this.props;

    return (
      <div>
        <ToDoItem text="안녕"/>
        <ToDoItem text="리액트"/>
        <ToDoItem text="반가워"/> 
      </div>
    );
  }
}

export default ToDoItemList;

 

그 다음 ToDoItemList를 App에서 불러온 다음 렌더링

src/App.js

import React, { Component } from 'react';
import ToDoListTemplate from './components/ToDoTemplate';
import Form from './components/Form';
import ToDoItemList from './components/ToDoItemList';


class App extends Component {
  render() {
    return (
      <ToDoListTemplate form={<Form/>}>
        <ToDoItemList />
      </ToDoListTemplate>
    );
  }
}

export default App;
반응형
복사했습니다!