[React] todoList 만들기

노유성·2023년 4월 11일
0
post-thumbnail

기본 구조

![]https://velog.velcdn.com/images/shdbtjd8/post/92e6f7bb-a5a4-4d3b-8651-86ec28bb8042/image.png)

jsx문법으로 공부하기 버튼을 만든 예시이다. html문법과 매우 흡사하며 html을 작성하던 중 js 요소가 들어가야 할 때는 { } 안에 작성한다.

기본 설정

index.css

body {
background-color: aliceblue;
}

index.css 파일에 전체 화면의 바탕색을 설정한다.

App.css

.container {
margin: auto;
max-width: 600px;
}
.todoBlock {
padding: 30px;
margin-top: 50px;
background: #fff;
border-radius: 10px;
box-shadow: -9px 17px 13px rgb(0 0 0 / 16%);
}

App.js에서 만들 element들을 꾸며줄 css를 설정한다.

import './App.css'

위 js코드를 통해서 css파일을 불러올 수 있다.

위 css들을 적용해서 꾸민 예시를 보면은


이런 UI가 만들어진다.

태그에 Style 주는 법

1. class 속성

가장 기본적인 방법이다. css 파일을 import한 후 다음과 같이 스타일을 class 속성에 넣어준다.

주의해야 할 점은 html과 다르게 className으로 속성을 지정해주어야 한다는 것이다.
이유는 js에서 class는 예약어이므로 중복을 방지하기 위해서이다.

2. object

1번과 다르게 컴포넌트 내에 스타일을 정의한 object를 inline을 적용하는 방법이다.


btnStyle은 App class 안에 정의된 instance variable 이므로 위 그림과 같이 this키워드를 통해서 지정해주어야 한다.

3. method

2번과 마찬가지로 inline으로 스타일을 지정하는데 값이 정해진 object를 지정하는 것이 아니라 method의 리턴값으로 지정하는 방식이다.


왜 이런 방식을 사용할까?
함수의 특성을 이용해 상황에 따라 변칙적으로 style을 주기 위해서이다.

다음 코드를 예를 들어보자면

위 코드는 특정 data를 담긴 list를 받아 map을 통해 component를 list의 요소만큼 만드는 것이다.
list의 각 요소는 object이며 {id, title, completed} 3개의 property가 있다.

간단하게 구성을 살펴보면 element마다 하나의 div태그를 만들고 그 안에 element의 property를 바탕으로 만드는데 주목할 점은
div 태그의 style 부분이다.

inline style에 this.getStyle()의 리턴값을 지정하고 인자로 data.completed를 넘겨주고 있다.


\getStyle()에서 정의된 textDecoration 값이 인자로 받은 값에 의해 다르게 적용이 되며 결론적으로 completed 값에 따라서 div 태그의 style이 다르게 적용되는 것이다.

한 줄 요약하자면, literable한 객체를 이용해 element를 만들 때 element들 마다 다른 특징을 이용하여 다른 스타일을 주고싶을 때는 고정된 class를 여러 개 만드는 것이 아니라 하나의 method로 여러 스타일을 줄 수 있다.

Key 속성

앞서 살펴본 그림 중에 map method를 이용해 여러 개의 div 태그를 만드는 구문에서

key값을 태그에 할당하는 것을 볼 수 있다. 직관적으로도 알 수 있듯이 key는 id속성과 비슷하게 각각의 태그들을 react가 구분하기 위한 속성이다.

같은 태그를 가지는 형제 노드들끼리 key 속성이 없다면 다음과 같은 에러가 발생한다.

literable를 이용해 여러 형제 노드들(태그들)을 만들면 발생하는 에러인데 에러가 발생하는 이유는
react가 새로 생겨난 노드들을 key값을 통해서 찾고 랜더링을 하는데 key값이 없으면 어떤 노드가 새로 생겨난 노드인지를 구분할 수 없기 때문이다.


이 경우에는 react가 3번 노드가 새로 생겨났다는 것을 앞에 1,2 를 통해서 확인한다.

하지만

이 경우에는 react가 3번 노드를 제일 먼저 만나고 모두가 새로운 노드라고 인식해 전부다 렌더링을 하고 이는 불필요한 자원이 소모되는 것이다.

즉 key값이 없다면 react는 명확하게 노드를 구분하지 못 하고 순차적으로 노드를 확인해가면서 확인하기 때문에 순서가 하나라도 뒤틀린다면 전부다 렌더링을 하는 비효율적인 사태가 발생한다.

React State

컴포넌트 렌더링에 영향을 주는 데이터를 의미한다. 데이터가 변경되면 해당 데이터를 참조하고 있는 모든 컴포넌트는 리렌더링을 하게 되고 이러한 영향력을 갖고 있는 데이터를 State라고 명명한다.

생성하기

setState() method를 이용한다.

사진과 같이 State Object안에 Property로 State data들을 넣어준다.
위 그림에서는 todoData, value라는 두 개의 state data가 존재하는 것이며 두 데이터가 변경되면 두 데이터를 참조하는 모든 component는 리렌더링된다.

변경하기

다음은 state data를 변경하는 예제이다.

handleCLick()은 id값을 인자로 받는 화살표함수이며, state data인 todoData(list이기에 literable함)를 filter method를 이용해 새로운 list를 만든 후 newTodoData에 저장한다.

저장한 데이터를 setState() method를 통해서 갱신한다.
주목할 점은

  • this 키워드를 사용
  • setState()의 인자에 객체 { } 데이터를 넣음

이다. State는 object이므로 형식을 맞춰서 넣어주어야 한며 setState는 class의 instance method이기 때문에 this 키워드를 통해서 호출해야한다.

그런데 우리는 setState() method를 정의한 적이 없다. 어디서 왔을까?

Component class


우리가 만든 App class는 Component class를 overriding해서 만든 class이기 때문에 setState()가 이미 Component에 정의되어 있다.
또한 setState()가 state 변수를 참조하도록 정의되어 있기 때문에 우리가 state 변수 안에 property로 state data를 선언하고 이용한다.

preventDefault()

form 태그에서 submit을 하게 되면 페이지가 리로드가 된다. 그러면 해당 페이지에서 저장하고 있었던 내용이 다 사라지고 새로운 페이지가 열리기 때문에 submit을 포함해 리로드를 하는 경우에는 preventDefault() method를 이용해서 브라우저에서 기본적으로 작동하는 기본 이벤트를 멈출 수 있다.

여기서 우리는 submit 시에 페이지가 리로드되는 것이 브라우저에서 기본적으로 사용하고 있는 event임을 알 수 있다.

예시



submit이 발생 시에 수행할 동작은 { }안에 정의한다.
handleSubmit()은 함수가 시작됨과 동시에 preventDefault()를 수행한다.

여기서 첫 번째 그림을 자세히 살펴보면 인자를 받는것을 알 수 있다. 하지만 우리는 e를 정의한 적이 없는데 e는 무엇이고 어디서 오는 것일까?

이벤트 객체

브라우저는 폼을 제출할 때 'onSubmit' 핸들러에 이벤트 객체를 전달한다.
이벤트 객체는 발생한 이벤트가 발생한 요소와 관련된 정보를 다룬다.

그래서 우리는 자동적으로 브라우저가 전달해준 event 객체를 받아서 preventDefault()를 사용할 수 있는 것이다.

조금 더 나아가서 생각하자면, 반대로 우리가 onSubmit 핸들러를 작성하지 않으면 이벤드 객체가 전달되어도 아무것도 수행하지 않게 되고 브라우저는 기본 동작을 수행한다.

onClick, onChange, onSubmit 등 on으로 시작하는 모든 것들은 react에서 이벤트 핸들러를 등록할 때 사용하는 이름 규칙이다.
html에서는 onclick, onsubmit 등 모든 글자를 소문자로 작성하지만 react에서는 on 뒤의 첫번째 알파벳은 대문자로 작성한다는 점을 유의하자.

이벤트 버블링

일반적으로 태그들은 서로 부모 자식관계를 가지고 있으며 이는 트리 구조를 지닌다.
그리고 특정 태그에서 이벤트가 발생하면은 해당 태그를 기점으로 조상 태그까지 모든 태그에 발생한 이벤트가 전달되며 이를 우리는 이벤트 버블링이라고 한다.

예시


위 사진에서 93번째 form 태그에 onSubmit에 대한 이벤트 핸들러가 등록되어 있다.
하지만 자세히 보면 이를 감싸고 있는 81번째 최상위 div태그도 onSubmit에 대한 이벤트 핸드러가 등록되어 있다.(div태그엔 submit 이벤트가 없다)

이론대로라면 form 태그에서 발생한 submit 이벤트는 div 태그까지 이벤트 버블링 되어 전달될 것이고 div 태그에서는 이벤트를 받아서 등록되어있는 eventBubbling 이벤트 핸들러가 작동할 것이다.


다음과 같이 콘솔에 값을 찍은 이벤트 핸들러를 등록한 뒤에

입력 버튼을 누르면

이벤트 버블링 덕에 이벤트가 전달되어 div 태그에 등록된 이벤트 핸들러가 작동한다.

이 부분이 이점으로 작용할 수도 있지만 단점으로 작용하는 경우에 이벤트 버블링을 막는 stopPropagation() method가 있다고 하니 특정 태그의 이벤트 핸들러에 등록하면 버블링을 막을 수 있다.

더하여

정리하자면 특정 태그에서 발생한 이벤트는 이벤트 버블링을 통해서 모든 이벤트 핸들러에 전달된다. 하지만 이벤트 핸들러가 등록되어 있지 않다면 브라우저가 undefined를 전달한다.

즉, 이벤트 핸들러가 있으면 이벤트를 아니라면 undefined를 전달하고 전달한 내용은 핸들러(콜백함수)의 첫번째 인자로 전달된다.

profile
풀스택개발자가되고싶습니다:)

0개의 댓글