본문 바로가기
source-code/React

리액트를 다루는 기술 _ 10장 - 2

by mattew4483 2021. 3. 16.
728x90
반응형

2021.03.14 - [Frontend/React] - 리액트를 다루는 기술 _ 10장

 

리액트를 다루는 기술 _ 10장

어찌저찌 10장까지 도착! 10장. 일정 관리 웹 애플리케이션 만들기 지난번 JS 만으로 만들었던 To-Do App! 이번에는 React로 도전해보자. 10-1) 프로젝트 준비하기 새로운 앱을 만들어주자! 우리의 친구

23life.tistory.com

이어지는 글!


10-3) 기능 구현하기

1. App에서 todos 상태 사용하기

나중에 추가할 일정 항목들은 모두 App 컴포넌트에서 관리!

App.js

우선 todos라는 상태를 정의(useState 사용)하고, 이를 TodoLiust의 props로 전달해줬다!

 

이때 todos 배열 속 객체에는 각 항목의 고유 id, 내용, 완료 여부 값 이 포함되어 있다.

 

TodoList.js

App에서 props로 보낸 todos 배열을 TodoList에서 받아, TodoListItem으로 변환해 렌더링 하도록!

 

TodoListItem.js

각 항목 하나하나를 담당하는 TodoListItem!

그런데 className에 따른 조건부 스타일링을 이용하기 위해 classnames란 모듈을 설치해준다.

요 라이브러리를 통해 className에 다양한 옵션을 붙여 사용할 수 있다.

<div className={classNames()}/>의 기본형태!

classNames 안에서 true에 해당하는 값은 추가로 표시가 가능하고, false인 값은 className에 적용되지 않는다!

 

여기서 todo를 정의해줬으며, checked의 true/false에 따라 다른 CheckBox가 보인다!

 

http://localhost:3000/

이런... 식으로..!

 

2. 항목 추가 기능 구현하기

항목을 추가하기 위해서는?

TodoInsert 컴포넌트에서 input에 입력하는 값을 관리할 수 있도록,

useState를 사용해 value라는 상태를 정의한다!

 

TodoInsert.js

onChange 함수를 통해 변화가 생길 때마다 해당 값(e.target.value)을 추적!

이를 value로 넣어준다.

input 창에서 입력하면 해당 값이 value에 잘 들어가는 모습!

 

다음으로 App 컴포넌트에서 todos 배열에 새 객체를 추가하는 onInsert 함수를 만들 예정!

App.js

으악 엄청 길다!

 

사실 여기만 보면 된다..!

 

todo별 key로 사용할 고유 번호를 생성하기 위해 useRef로 nextId란 녀석을 설정!

 

역시 TodoInsert 컴포넌트에 onInsert를 props로 전달해줬는데...

우선 요 녀석은 props니 useCallback 함수를 사용해 [todos]에 변화가 생길 때만 작동하도록!

 

onInsert 함수가 작동되면 전달받은 text로 새로운 항목(todo)을 생성하며,

이때 todo의 id는 현재 nextId 값을, text는 전달받은 text를, checked 속성은 false로 설정해준다.

 

concat을 통해 이렇게 만들어진 todo가 추가된 list인 todos를 새롭게 생성!

고유한 값인 nextId의 숫자도 빼먹지 않고 하나 더해줬다.

 

다음으로는...

방금 App에서 TodoInsert에 넣어 준 onInsert 함수에 현재 useState로 관리하는 value 값을 넣어 호출!

이게 뭐신디? → 버튼이 클릭되면 이벤트를 발생시켜, onInsert가 작동되게 할 거다!

 

TodoInsert.js

역시 쫌 길어 보이지만... 눈여겨볼 부분은 onSubmit 함수!

요 녀석은 form의 onSubmit 이벤트로 호출되는 녀석이다.

 

그런데 왜 onClick 대신 onSubmit을 사용한 것?

→ onSubmit은 엔터키만 눌러도 이벤트를 발생시키지만,

onClick은 엔터키 누르면 버튼 누른 걸로 치는 코드를 따로 짜줘야 한다!

(즉 form과 onSubmit 대신 onClick으로 해도 좀 귀찮을 뿐이지... 상관은 없다!)

 

문제는 onSubmit은 이벤트 발생시마다 페이지를 세로고침 한다는 점.

따라서 e.preventDefault를 호출해 이를 막아줬다.

 

아무튼 요 onSubmit 함수가 실행되면,

props로 받아온 onInsert에 value 값을 넣어 호출해, 새로운 todos가 생성될 테다!

 

희한도 하게 작동이 된다.

 

JS와 느낌이 굉장히 굉장히 굉장히 다른 느낌이다.

왜인고 생각해보니...

JS의 경우 익숙한 Django의 ORM을 이용해 list를 생성하고 보여주는 것과 느낌이 비슷했다.

 

그러나 React는...

하나의 list에 요소를 추가하기 위해서는 ↓

list 내 요소 정의 / 각 요소 생성 구현 / 각 요소 입력 구현 /

각 요소 전체 list에 추가 구현 / 요소 확정(제출 or클릭) 구현 등...

당연하다고 생각했던 요소들을 하나하나 만들어줘야 하는 느낌!

이 때문에 이런 것도 필요한 것인가...! 란 기능들까지 구현이 필요했다. 흐아.

 

3. 지우기 구현하기

지우기 → 불변성을 유지하면서, 동시에 배열 요소가 제거된 새로운 리스트를 반환해야 한다.

딱 맞는 녀석이 바로 filter 함수.

 

요 녀석은 기존 배열을 그대로 둔 상태에서

특정 조건을 만족하는 원소들만 따로 추출해 새로운 배열을 만들어 준다!

 

따라서 filter 함수에는 조건을 확인해 주는 함수를 파라미터로 넣어 줘야 하며,

이때 해당 함수는 true 혹은 false 값을 반환해야 한다! (true 반환하는 경우에만 새로운 배열에 포함)

 

이를 이용해... App 컴포넌트에서 id를 파라미터로 받아와,

해당 id를 가진 항목을 todos 배열에서 지우는 함수를 만들어보자!

App.js

해당 부분이 추가!

 

역시나 만든 onRemove함수를 TodoList에 props로 넘겨주자!

 

그런데 todo의 id만 구하면 되는 것 아닌가? 왜 TodoList에 props를 넘겨준 것?

→ 왜냐면 App에서는 TodoList 컴포넌트를 거쳐, TodoListItem으로 가야 하니까!

 

TodoList.js

즉 당연히 TodoList에서 TodoListItem에 onRemove 함수를 전달해주시고,

 

TodoListItem.js

TodoListItem에서 삭제하고자 하는 todo의 id를(onClick 이벤트가 발생한 todo) 받아와 onRemove함수에 쏙!

 

삭제도 정상적으로 이뤄지는 모습!

 

마지막으로, check 버튼을 누르면 체크 버튼과 글씨가 수정되도록 바꿔보자.

삭제와 유사하게 App에 수정 함수를 만들고, TodoList에 props로 넣은 후, TodoListItem에 전달하면 된다!

 

App.js

삼항 연산자를 통해 todo.id가 id와 같은 녀석들을 가려내 줬다!

 → 같은 녀석들의 checked 상태를 반전!

 

또한 map을 이용함으로써 id를 통해 checked를 바꾼 todo들로 이뤄진 새로운 todos를 반환해줬다.

 

역시나 onToggle이라는 props로 요 함수를 전달!

 

TodoList.js

역시나 TodoList에서 TodoListItem으로 전달해주시고,

 

TodoListItem.js

checkbox를 클릭하면 onToggle함수에 해당 todo의 id를 전달!

onToggle함수에 의해 해당 todo의 checked가 바뀔 테다.

 

http://localhost:3000/

모든 기능이 정상적으로 작동하는 모습!


책을 따라가며 어찌어찌 완성을 했는데...(완성 못하는 게 바보다)

이를 혼자 만든다고 생각하면? 앞이 캄캄캄.

 

책은 뭔가... 전지적 개발자 시점에서 코드를 작성하는 것 같달까.

(최상위 컴포넌트인 App에서 최하위 컴포넌트인 TodoListItem의 상태를 막 쓴다던가...)

결국 자주 만들어보면서 익숙해지는 수밖에 없는 것 같다! 흐야야.

728x90
반응형