Udemy - React완벽가이드
리액트 state 및 이벤트 다루기
Hanachoi
2023. 2. 18. 15:23
#이벤트 리스닝 및 이벤트 핸들러 수행하기
- 현재까지 만든 페이지는 정적인 상태이고 하나의 초기상태(state)만을 가지고 있다.
- 현재상태에서 간단하게 상태(state)를 바꿀 수 있는 버튼을 하나 만들어보자.
- <h2>{props.title}</h2>의 상태를 바꿀 버튼을 만들어 줄 것이다.
- 리액트에서는 버튼이 클릭되었을 때 어떻게 반응할까?
- 기본 html element같은 기본 DOM 이벤트 요소에 모두 접근이 가능하다.
- MDN 문서에서 찾아보면 우리는 기본 element event 들을 볼 수있는데, 얘네들은 리액트에서 props와 동등한 것것으로 내장된 html 요소에 추가해서 이런 이벤트들을 수신할 수 있다.
- https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement
HTMLButtonElement - Web APIs | MDN
The HTMLButtonElement interface provides properties and methods (beyond the regular HTMLElement interface it also has available to it by inheritance) for manipulating <button> elements.
developer.mozilla.org
- 기존 JS 에서는 명령형 방식을 썼다.
document.getElementByID('root').addEventListener()
- 리액트에선 JSX element를 사용해 이벤트 리스너를 추가하는데, 여기에 special props를 추가해준다. 리액트에서는 이 props가 props로 이름 지어진게 아니고 대신 on으로 시작하는 props를 넣어준다. 리액트에서는 디폴트 리액트는 모두 on으로 시작한다.
- 클릭됬을 때 이벤트가 실행되게 하기 위해 onClick을 props로 button에 넣어주고 이 onClick을 정의해줘야 한다. 이 때 정의된 코드는 중요하고 물론 클릭되었을때 실행되는 코드여야 한다. 어떻게 실행되게 해줄 수 있을까? 함수를 정의해줘야 한다.
- 모든 'on' props나 이벤트리스너는 함수가 필요하고 이벤트가 발생되었을 때 실행되어야 한다.
- 아래의 이미지처럼 onClick을 붙여주고 그 안에서 바로 함수를 만들어 줄 수 도 있다. 하지만 이렇게 인라인으로 달아주기보다 위에 따로 함수를 만들고 추가해주는게 더 좋다. JSX 코드에는 너무 많은 로직을 넣지 않는게 좋기 때문

- 위에 따로 함수를 만들어 주고 onClick부분에는 포인터처럼 그 함수를 넣어주는게 더 깔끔하게 유지된다.
- 원래 기존 자바스크립트라면 onClick ={clickHandler()}처럼 ()를 함수 뒤에 넣어줄 것이다. 하지만 JSX에서는 그냥 가리키기만 하면 된다.
- 만약에 저렇게 ()를 넣어주면 자바스크립트가 이걸 실행하게 되고 JSX코드가 평가될 때 실행된다. 그렇게 되면 너무 빠르게 실행되는 것이기 때문에 우리가 버튼을 클릭했을때 실행되도록 그냥 clickHandler를 지정해주기만 한다.

- 함수의 이름 짓는 법
- clickHandler처럼 이벤트 명을 앞에 붙여주고 그 뒤에 Handler로 붙여준다.
#컴포넌트 기능이 실행되는 법
- 어떻게 화면이 바뀌게 만들 수 있을까? 버튼이 클릭되었을때 <h2>{props.title}</h2>을 바꾸게 하려면?
- let을 사용해서 title이라는 변수를 만들어서 props.title을 바로 넣어준다. 그리고 clickHandler함수가 실행되면 title을 'updated'로 바꿔주면 될 것이다. 일단 title이라는 변수를 만들었다면, 변수이기때문에 clickHandler 함수로 값을 바꿔줄 수 있을 것이다.

- 하지만 이렇게 해도 title은 직접적으로 변하지 않는다!!! 왜그런 걸까? conosl.log에 찍어보면 그대로 updated의 값이 나오기 때문이다. 하지만 화면에 직접적으로 반영되지 않는다. 리액트는 이런식으로 작동하지 않기 때문이다.
- 우리의 컴포넌트는 함수다. 이 함수의 특별한 점은 JSX 코드를 반환한다는 점이다.
- 우리의 컴포넌트는 함수이기때문에 사용을위해서는 호출이 되어져야 한다. 하지만 우리는 아직 함수를 호출한 적이 없다. 대신 JSX코드안에 있는 HTML코드 같은 것들을 사용해왔다. 사실 얘들은 함수처럼보이진 않지만 함수처럼 사용해왔다. 리액트가 우리의 컴포넌트 함수를 인식하도록 한것이다.

이런 컴포넌트 함수들은 모든 평가된 JSX 코드를 반환하려고 한다. 평가할 JSX코드가없을 때까지 말이다.
그래서 리액트는 JSX에서 마주치는 컴포넌트 함수들을 계속해서 호출한다. 어떤 JSX 코드가 남아있지 않을 때까지 그런 컴포넌트의 어떤 요소들이 사용될수도 있다.
리액트의 유일한 문제는 절대 반복하지 않는다는 것이다. 응용프로그램들이 첫번쨰로 렌더링 되었을 때, 그 모든 과정을 실행하고 그 이후는 끝이다.
우리는 물론 화면에 보이는 것들을 업데이트하고 싶을 것이다. 버튼이 클릭되면 텍스트들이 변경되는 식으로 말이다. 그래서 우리는 리액트에게 무언가가 바뀌고 재평가되어야되는지를 말해줘야한다. 그래서 나온 개념이 State이다.
# "State"와 함께 일하기
- state는 리액트에서 특화된 아이디어는 아니지만 상당히 중요한 개념이다.
- 위에서 본 예시처럼, 버튼이 클릭되면 컴포넌트가 재평가되면서 상태가 업데이트 되어야 하지만, 리액트에서는 한번 랜더링이 실행 된 뒤에는 이런 재평가로는 실행되지 않는다. 컴포넌트 함수에서 변수를 가지고 있고 변수가 변경되었다고 해도 리액트는 무시하고 코드가 실행되어도 무시한다.
- <ExpenseITem >컴포넌트에서도 버튼이 클릭되었을때 이 컴포넌트 함수를 다시 실행해서 상태를 바꾸라고 명령하지 않는다.
- 그래서 우리는 리액트에게 다시 실행하라고 말해줘야 한다.
- 우리는 리액트라이브러리에서 특별한 함수를 호출해줄 수 있다.
- useState라는 함수를 불러보자
- 디폴트로 부른 React 옆에 { }를 사용해 내장된 리액트 함수인 useState를 불러올 수 있다.

- useState는 컴포넌트 함수가 다시 호출되는 곳에서 변경된 값을 반영하기 위해 state로 값을 정의할 수 있게 해주는 함수이다.
- 사용법
- 컴포넌트 함수 안에서 불러준다. useState는 리액트 훅 중 하나인데, 여러가지 훅들이 존재한다. 이 모든 훅들은 컴포넌트 함수 안에서 불려야 사용이 가능하다.
- 중첩된 함수안에서도불릴 수 없다. 꼭 컴포넌트 함수안에서 직접적으로 호출되어야 한다.
- 우리는 useState로 특별한 종류의 변수를 생성한다고 말할 수 있다. 변수는 변경사항으로 인해 컴포넌트 함수가 다시 호출되도록 할 것이다.
- 우리는 이 변수에 대한 초기값을 할당할 수 있는데, 이걸 useState에 인자로 전달한다.

- useState는 특별한 변수를 반환하는데, 그 변수로 상태를 변경할 수 있도록 해준다. 또 우리가 상태를 바꿀 수 있도록 호출할 수 있는 함수도 반환한다.
- useState는 배열을 하나 반환하는데, 첫번째 값은 변수자체, 두번 째 값은 업데이트되는 함수이다. useState는 언제나 이런 형태로 반환된다.
- 배열 디스트럭처링을 사용한다.

- const [관리되고 현재 상태 값 , 나중에 새로운 값을 설정하기위해 호출할 수 있는 함수 ] = useState()
- 이름은 맘대로 설정할 수 있지만, 보통 두번째 값은 set을 붙여서 설정해준다.
- 이제 clickHandler 함수에 직접적으로 변수를 넣어주는게 아니라. setTitle 함수를 호출해서 새 값을 할당해 줄 수 있다. 인자로 새로운 값을 전달하면 된다. 이 경우에는 'updated'

- 왜 title = 'updated' 대신 setTitle을 이용해서 새 값을 전달할까? 우리는 단지 새로운 값만 받는게 아니라 우리가 호출한 컴포넌트 함수가 이 state를 업데이트 해준다. useState로 상태를 초기화 했던곳에서 다시 실행될 것이다.
- 우리가 stae가 변할때, 컴포넌트 함수를 다시 호출해주고 싶으면 이 state를 업데이트 해주는 setTitle 함수를 부르면 되는 것이다. 우리는 함수를 불러 새로운 값을 넣고 state가 등록된 컴포넌트가 재평가되어야 한다고 리액트에게 말해주는 것이다.
- 리액트는 컴포넌트함수를 다시 실행하고 또 JSX코드를 다시 평가한다. 그리고 지난번과 비교해서 나타난 변화를 화면에 나타나게 해준다.
- 결론적으로, 리액트에서 상태를 변화시키고 싶으면 일반 변수를사용하는게 아니라 useState를 써서 상태를 변경해야 된다. state가 변경되면 리액트는 그 state가 등록된 컴포넌트를 재평가하게 된다.