개발/React

리액트 투두앱 간단하게 만들기 - 10분만에

재근이 2021. 10. 16. 18:15
반응형

 

투두앱

🚀간단하고 빠르고 쉽게 만들자

이번 글에서는 그렇게들 다들 한 번씩은 만든다 Todo App을 빠르게 만들어보자.

따로 CSS 등 디자인은 적용하지 않고, 기능적인 것만 구현해보자.

리액트 시작하기 1, 2에서 배운 것들만 이용하여 쉽고 간단하고 빠르게 만들예정이다.
리액트 기초는 알고 있어야 만들 수 있다.
혹시 아직 리액트 기초를 모른다면 아래 글에서 기초만 배우고 오도록 한다.

 

리액트 시작하기 1 - 설치 및 기본 예제 분석

이 글은 기본적으로 HTML/CSS/Javascript의 기본은 알고 있다는 전제하에 작성되어 있습니다. 잘은 몰라도 되지만 어느 정도 기본 개념은 알고는 있어야 이해하기 쉽습니다. 💾node js 설치 React를 사용

jaegeun.tistory.com

 

리액트 시작하기 2 - Component로 기본 끝내기

❗이 글은 "리액트 시작하기 1"을 이해했다는 가정하에 진행되므로, 리액트 기본 개념을 아직 모른다면 "리액트 시작하기 1"을 보고 오는 것을 추천드립니다. 🚀Component로 기본 끝내기 Component의

jaegeun.tistory.com

 

🎨구조 그리기

우선 전체적인 Component 구조와 보이는 화면에 대해 구조를 잡아보자.
그림은 내가 그려놨으니 빠르게 확인하고 넘어가자.

Component 구조
화면 구조

 

📁리액트 폴더 구조

create-react-app을 해서 프로젝트를 생성하고 아래와 같이 사용하지 않는 파일들은 제거를 했다.

우선  Component 파일들을 생성해서 아래 폴더 트리와 같이 만들어 주자.

폴더 트리

 

📝코드 작성 및 설명

먼저 기본 골격을 잡은 후, Todo 앱의 기능들을 하나씩 구현해보자.

 

🏗기본 골격 구조 작성 Index.js / App.js / Title.js / Content.js

우선 간단한 Index.js/App.js/Title.js 3가지 파일은 간단하기에 빠르게 작성하고 넘어가자.
그러고 나서 Content.js골격까지 잡는 코드를 작성해보자.

📄Index.js
프로젝트 생성 시 그대로 사용하면 된다.

📄App.js
<div> 태그 안에 곧 만들어줄 TitleContent Component를 넣어준다.
Title Component에는 괜히 "Todo List"라는 text를 props로 넘겨주자.

import { Component } from "react";
import Title from './Title'
import Content from './Content'

export default class App extends Component {
	render() {
		return (
			<div>
				<Title text="Todo List" />
				<Content />
			</div>
		);
	}
}

📄Title.js
사실 특별한 내용은 없어서 필요 없는 Component지만 만들어줬다. (귀찮으면 빼자)
App Component에서 전달받은 text를 출력해준다.

import { Component } from "react";

export default class TitleBar extends Component {
	render() {
		return (
			<div>{this.props.text}</div>
		);
	}
}

📄Content.js
Content의 기본 골격만 잡아보자.

import { Component } from "react";

export default class Content extends Component {
	render() {
		return (
			<div>
				<input autocomplete="off" id="inputText" type="text" placeholder="입력"></input>
				<input type="button" value="↩"></input>
			</div>
		);
	}
}

기본 골격만 구현

기본 골격 코드까지 작성하고 나서 npm start로 동작시켜보면 기본 UI화면이 나온다.
아직은 기능을 구현하지 않았기에 특별히 동작하지는 않는다.

 

👨🏼‍💻기능 작성 Add / Check / Delete

기본 골격은 작성했으니 이제 기능들을 하나씩 만들어보자.

📄TodoList 추가
Add 기능을 구현하기 전에 Add 해서 넣어줄 TodoList Component를 작성해서 추가해주자.
우선 Content에서는 TodoListItem을 관리하고 있는 배열을 state로 생성해주고, propsTodoListItem를 넘기도록 수정하자.

📄TodoList.js
TodoList Component에는 props로 전달받은 items<ul> 태그 안에서 출력되도록 작성하자.

import { Component } from "react";

export default class TodoList extends Component {
	render() {
		return (
			<ul> {this.props.items} </ul>
		);
	}
}

 

📌Add 기능

TodoListItem을 만들기 전에 Content에서 글자 입력 후 버튼을 누르면 this.state.items에 입력한 글자들이 <li> 태그로 감싸 져서 추가되도록 해보자.

만들어둔 button에 클릭(onClick) 이벤트를 달아주고, 이벤트가 발생 시 addItem이라는 함수가호출되도록 한다.

addIteminputText라는 id를 가지는 input 태그의 값을 읽어오고. this.state.items에 <li> 태그로 감싸서 추가한다.

이때 주의해야 할 점this.state.items에 바로 push 하면 안 되고, 배열을 복사([...배열]방법)한 후에 복사한 배열에 push를 해야 한다. 그러고 나서 복사한 배열을 setState로 변경해줘야 한다.

여기까지 하면 아래와 같이 추가되는 기능을 구현한 것을 볼 수 있다.

추가 기능

📌Check 기능

Check 기능은 TodoListItem Component를 만들고 그 안에서 동작되도록 할 거다.
TotoListItem 코드를 우선 작성해보자.

📄TotoListItem.js

import { Component } from "react";

export default class TodoListItem extends Component {
	checkItem() {
		const checkComponent = document.querySelector("#todo-item" + this.props.id);
		if (checkComponent.style.cssText) {
			checkComponent.style.cssText = 0;
		} else {
			checkComponent.style.cssText = "text-decoration: line-through";
		}
	}
	render() {
		return (
			<li id={"todo-item"+this.props.id}>
				<input type="button" value="✅" onClick={()=>{this.checkItem()}}/>
				{this.props.text}
			</li>
		)
	}
}

TodoListItem li 태그로 감싸 져 있고 props로 받은 id 값을 이용하여 id를 부여하고 있다.
그 안에는 props로 전달받은 text를 출력해주고 있으며, Check 기능을 위한 Button이 생성되어 있다.

Button을 누르게 되면 props로 전달받은 id값을 이용하여 item을 찾고,
취소선이 토글 되도록 CSS style값을 토글 해준다.

Content 수정
이제 Content Component에서 item 추가 시 직접 li 태그를 추가했던 것 대신에 방금 만든 TodoListItem Component로 추가되도록 수정해주자. props식별을 위한 itemNum 값도 잊지 말고 같이 넘겨주자.

여기까지 하면 Delete 기능을 제외한 기능을 구현했다.

 

📌Delete 기능

Delete 기능을 위한 버튼TodoListItem추가해주자.
Delete 기능은 상위 ComponentContent에서 해줘야 하기 때문에 id값을 Content로 전달을 해줘야 한다.
"리액트 시작하기 2" 글에서 배운 event를 이용해서 id 값을 전달되도록 해주자.
버튼이 눌리면 this.props.delete라는 event가 호출되도록 해줬다.

Content Component에서는 delete이벤트를 발생 시 해당 iditem제거될 수 있도록 코드를 수정하자.

최종 완성

delete 기능까지 만들었고, 이제 실행시켜보면 이 글의 맨 위에서 봤던 거처럼 완성이 되었다.

📄Content.js
최종적으로 수정된 Content.js코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { Component } from "react";
import TodoList from "./TodoList"
import TodoListItem from "./TodoListItem"
 
export default class Content extends Component {
    constructor(props) {
        super(props);
 
        this.state = {
            itemNum: 0,
            items: [
            ]
        };
    }
 
    deleteItem(num) {
        const selected = document.querySelector('#todo-item'+num);
        if (selected) {
            selected.remove();
        }
    }
 
    addItem() {
        const inputText = document.querySelector('#inputText');
        if (inputText.value) {
            const tempArr = [...this.state.items];
            tempArr.push(<TodoListItem
                id={this.state.itemNum++}
                text={inputText.value}
                delete={(num)=>{this.deleteItem(num)}} />);
            this.setState({
                items: tempArr
            })
            inputText.value=""
        }
    }
 
    render() {
        return (
            <div>
                <input autocomplete="off" id="inputText" type="text" placeholder="입력"></input>
                <input type="button" value="↩" 
                    onClick={()=>this.addItem() }}
                />
                <TodoList items={this.state.items}/>
            </div>
        );
    }
}
cs

 

자 이렇게 쉽고 간단하게 끝났다. 여기에 CSSUI만 수정해주면 멋진 Todo앱으로 바꿀 수 있다.

반응형