React Project 책으로 삽질하기 2(나를위한 기록)
초반 스타일 작업
- 책에서는 scss를 사용하여 스타일 작업을 진행하지만 개인적으로는 css가 너무 익숙해서 css를 이용히여 책과 최대한 비슷하게 스타일 작업부터 진행하겠습니다.
.TodoListItem {padding:1rem; display:flex; align-items:center; border-bottom:0.1rem solid #dddddd;} .TodoListItem .checkbox {display:flex; flex-grow:1; align-items:center; cursor: pointer;} .TodoListItem .checkbox svg {font-size:2.4rem;} .TodoListItem .checkbox .text {margin-left:0.5rem; flex:1 0 0;} .TodoListItem .checkbox.checked {color:#868e96; text-decoration: line-through;} .TodoListItem .remove svg {font-size:2.4rem; color:#ff6b6b;}
- 해당 css를 추가한 후 컴포넌트 랜더링을 하면 아래와 같은 화면으로 변합니다.
기본 기능 구현하기_1(App.js)
- 화면에 나오는 모습은 단순하게 html과 css만을 이용해 만든 화면이므로 텍스트를 입력한 후 추가하거나 기존에 있는 할 일을 삭제하는 기능이 동작하지 않기때문에 해당 기능들을 추가하는 작업을 진행하겠습니다. 먼저 App.js 에서 todos 상태에 따라 달라지는 화면을 표현하기 위해 아래의 이미지와 같이 임시 데이터를 작성합니다.
import React, { useState } from 'react'; import './App.css'; import TodoTemplate from './components/TodoTemplate'; import TodoInsert from './components/ToddInsert'; import TodoList from './components/TodoList'; const App = () => { const [todos, setTodos] = useState([ { id: 1, text: '리액트 기초 알아보기', checked: true, }, { id: 2, text: '컴포넌트 스타일링 해보기', checked: true, }, { id: 3, text: '일정 관리 앱 만들어보기', checked:false, } ]) return ( <> <TodoTemplate> <TodoInsert /> <TodoList todos={todos} /> </TodoTemplate> </> ); } export default App;
기본 기능 구현하기_2(TodoList.js)
- App.js 수정이 끝났다면 두번째로 TodoList.js를 수정합니다. App.js 에서 todos 배열안에 있는 객체들의 고유id, text, checked값을 TodoList에 props 로 전달해주는데 TodoList에서는 해당 값들을 전달받은 후 TodoItem으로 변환하여 랜더링하도록 설정해줘야 합니다.
import React from "react"; import TodoListItem from './TodoListItem'; import './Todo.css'; const TodoList = ({todos}) => { return ( <div className="TodoList"> {todos.map(todo => ( <TodoListItem todo={todo} key={todo.id} /> ))} {/* <TodoListItem/> <TodoListItem/> <TodoListItem/> */} </div> ); }; export default TodoList;
기존에 작성되어있던 TodoListItem 컴포넌트들을 주석처리해준 후 작업을 진행합니다. 먼저 props로 todos를 받아오기 위해 {todos} 를 선언한 후 배열 내장함수 map을 통해 TodoListItem으로 이루어진 배열로 변환하여 랜더링 시켜줍니다. 아래 코드중에 cn 의 경우 classnames 를 사용했습니다. 해당 기능을 사용하기 위해서 터미널에서 npm install classnames 를 사용하여 라이브러리를 설치해줍니다.
기본기능 구현하기_3(TodoListItem.js)
- TodoList.js까지 수정이 끝났다면 마지막으로 TodoListItem.js에서 todos 를 받아와서 App.js에 입력한 값들을 정상적으로 보여주기 위해 수정해줍니다.
import React from "react"; import {MdRemoveCircleOutline , MdCheckBoxOutlineBlank , MdCheckBox } from 'react-icons/md'; import cn from 'classnames'; import './Todo.css'; // import './TodoListItem.scss'; const TodoListItem = ({todo}) => { const { text,checked } = todo; return( <div className="TodoListItem"> <div className={cn(`checkbox`, { checked })}> {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />} {/* <MdCheckBoxOutlineBlank /> */} <div className="text">{text}</div> </div> <div className="remove"> <MdRemoveCircleOutline /> </div> </div> ); }; export default TodoListItem;
App.js, TodoList.js, TodoListItem.js 파일들을 수정 한 후 컴포넌트가 랜더링 된 모습을 보면 1, 2번 항목의 텍스트와 체크박스 모양이 정상적으로 바뀐 모습을 확인할 수 있습니다.
텍스트 앞에 체크박스에 체크가 된 텍스트들은 css에서 .TodoListItem .checkbox.checked {color:#868e96; text-decoration: line-through;} 를 통해 color와 text-decration을 통해 효과를 주었습니다.
할 일 추가하기 기능구현_1(TodoInser.js)
- 임시 데이터들이 정상적으로 출력되지만 input 영역에 텍스트를 입력하고 + 버튼을 눌럿을 때 아래의 할 일 리스트에 추가되는 작업을 진행하겠습니다. 먼저 TodoInsert.js 컴포넌트에서 input 값을 입력했을 때 해당 값을 관리할 수 있도록 value 상태를 정의해줍니다. 그리고 submit 이벤트가 작동할 때 자동으로 추가되는 이벤트값도 설정해줍니다.
import React, { useState, useCallback } from "react"; import { IoAdd } from 'react-icons/io5'; const TodoInsert = ({onInsert}) => { const [ value, setVlaue ] = useState(''); const onChange = useCallback(e => { setVlaue(e.target.value); }, []); const onSubmit = useCallback( e => { onInsert(value); setVlaue(''); // value값 초기화 // submit 이벤트는 브라우저 새로고침을 진행시키므로 아래 함수 호출 e.preventDefault(); }, [onInsert, value], ); return( <form className="TodoInsert" onSubmit={onSubmit}> <input placeholder="할 일을 입력하세요" value={value} onChange={onChange}/> <button type="submit"> <IoAdd /> </button> </form> ); }; export default TodoInsert;
위의 이미지에서도 볼 수 있지만 중간에 submit 이벤트가 실행될 때 브라우저 새로고침을 막기 위한 함수도 추가로 작성해줍니다.
할 일 추가하기 기능구현_2(App.js)
- TodoInsert.js 수정 작업이 끝난 후 다음번으로는 App.js에서 함수를 추가합니다. 해당 함수에서는 새로운 객체를 추가할 때 마다 id값에 +1을 더해주어 자동적으로 id값이 부여되게 해줍니다.
import React, { useState , useRef, useCallback } from 'react'; import './App.css'; import TodoTemplate from './components/TodoTemplate'; import TodoInsert from './components/TodoInsert'; import TodoList from './components/TodoList'; const App = () => { const [todos, setTodos] = useState([ { id: 1, text: '리액트 기초 알아보기', checked: true, }, { id: 2, text: '컴포넌트 스타일링 해보기', checked: true, }, { id: 3, text: '일정 관리 앱 만들어보기', 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; // nextId +1씩 증가 }, [todos], ) return ( <> <TodoTemplate> <TodoInsert onInsert={onInsert}/> <TodoList todos={todos} /> </TodoTemplate> </> ); } export default App;
# 결과보기
- 소스들이 정상적으로 작성되었다면 테스트를 진행합니다! 할 일을 입력히고 + 버튼을 클릭하면 4번째 줄에 추가로 입력한 텍스트가 추가되는 모습을 볼 수있습니다!
Comments