React

노마드코더 : React(영화 웹 서비스) - 4. state와 클래스형 컴포넌트

식초 2020. 12. 1. 21:28

state로 숫자 증감 기능 만들어 보기

state는 동적 데이터를 다룰 때 사용한다.

동적 데이터란 변경될 가능성이 있는 데이터이다.

예를 들어 객체의 구성 요소 중 일부가 있다가 없을 수도 있고, 구성 요소가 하나였다가 둘이 될 수도 있다.

 

 

클래스형 컴포넌트 작성하기

App.js에서 두 줄(맨 위, 맨 아래)만 남기고 모두 지운다.

 

 

클래스형 컴포넌트 코드

핵심은 App 클래스React.Component 클래스상속 받도록 extends React.Component붙인다.

 

'리액트가 제공하는 Component 클래스를 상속받는다' 의 뜻은?

 

상속은 '클래스에 다른 클래스의 기능을 추가할 수 있게' 해준다.

extends React.Component붙이면 (리액트가 제공하는 Component 클래스를 상속받으면)

App 클래스에는 React.Component 클래스에 있는 기능이 추가된다.

App 클래스가 React.Component 클래스기능을 상속 받은 것이다.

class App extends React.Component {

}

 실제로 React.Component 클래스는 500줄이 넘는 코드로 여러 기능이 구현되어 있다.

 

 

클래스형 컴포넌트가 JSX를 반환하려면 render()함수 사용한다.

cf. 함수형 컴포넌트는 JSX를 반환할 때 return()함수 사용한다.

리액트는 클래스형 컴포넌트의 render()함수자동으로 실행시켜준다.

render()함수는 직접실행하지 않아도 되는 함수이다.

 

클래스형 컴포넌트를 사용하는 이유는? state를 사용하기 위해서이다.

 

 

state 정의하기

class App extends React.Component{ } 안에 state = { };라고 작성한다.

state는 객체 형태이다. 

state를 사용하려면 반드시 클래스형 컴포넌트 안에서, 소문자를 이용하여 state라고 적으면 된다.

 

 

state에 count값 추가하고 사용하기

state에 count라는 키를 추가하고 키값으로 0을 넣는다.

render()함수에서 {this.state.count}를 출력한다.

this.state는 현재 클래스에 선언한 state를 의미한다.

state에 동적 데이터(바꿀 수 있는 데이터)를 저장해야 한다.

버튼을 클릭하는 등의 '사용자 동작'에 따라 state의 count를 바꿀 수 있도록 코드를 작성한다.

 

 

버튼을 눌러서 count state 값 변경해 보자

<Add>버튼과 <Minus>버튼 추가한다.

<Add>버튼 누르면 this.state.count의 값증가시킨다.

<Minus>버튼 누르면 this.state.count의 값감소시킨다.

 

함수 2개가 필요하다.

 

 

add()함수와 minus()함수 작성하기

 

버튼을 누르면 동작하도록 onClick 속성 추가하기

button 엘리먼트에 onClick이라는 속성을 넣고, 속성값으로 this.add와 같이 함수를 넣어 준다.

 

 

앱 동작 확인하기

브라우저에서 <Add>버튼 누르면 콘솔 탭에 문장이 출력된다.

 

 


숫자 증감 기능을 제대로 만들어 보기

리액트에서는 state를 특별하게 다뤄야 한다.

그래서 this.state.count++와 같은 코드를 아직 작성하지 말아야 한다.

 

 

this.state.count 마음대로 바꿔 보기

'state는 말 그대로 그냥 객체' 이므로 this.state.count =1 또는 this.state.count =-1로 값을 바꾸면,

콘솔에서 'Do not mutate state directly...' 경고 메세지가 뜬다.

state를 직접 변경하지 말라는 것이다.

리액트는 state를 직접 변경하는 코드를 허용하지 않는다. 그래서 버튼을 눌러도 0이 1이나 -1로 바뀌지 않는다.

 

자세히 설명하자면,

리액트는 state가 변경되면 render()함수를 다시 실행하여 변경된 state를 화면에 출력한다.

그런데 state를 직접 변경하는 경우 render()함수를 다시 실행하지 않는다.

 

 

경고 메시지 다시 살펴보기

> Do not mutate state directly. Use setState()

setSate()함수를 사용해서 state 값을 변경한다.

 

 

setState()함수로 count state 변경하기

setState()함수의 첫번째 인자count 키와 키값을 넣은 객체를 전달하자.

브라우저에서 count state가 1 또는 -1로 변한다.

 

setState()함수가 동작하면 state가 새로운 값으로 바뀌고, 이어서 render()함수를 동작시켜 화면을 업데이트 시킨다.

 

 

state의 변화에 따라 바뀌는 HTML 살펴보기

[Element]탭을 연 다음 <Add>버튼과 <Minus>버튼을 눌러보자.

HTML만 바뀐다.

리액트의 장점화면구성이 빠르다.(필요한 부분만 바뀐다.)

화면은 바뀌지만 새로고침이 일어나지 않는다.

 

 

버튼을 누르면 count state의 값을 증가 또는 감소시키기

{count : .... }와 같이 count state를 포함하여 객체를 setState()함수에 전달하면 count state가 업데이트된다.

 

성능 문제가 생길 수 있어서 이 방법은 좋지 않다.

setState()함수의 인자 함수를 전달하면 성능 문제 없이 state를 업데이트를 할 수 있다.

 

 

add, minus()함수 개선하기

current 인자를 받아 객체({count: current.count +1})를 반환하는 함수를 작성하여 setState()함수에 전달해 보자.

 

setState()함수는 바뀐 state의 데이터만 업데이트한다.

 

setState()의 인자로 state를 전달하면 어떻게 될까?

리액트는 이전 state새로운 state비교해서 바뀐 데이터만 업데이트한다.

변경 대상이 아닌 키와 키값은 그대로 유지된다.

 

 

 

 


클래스형 컴포넌트의 일생

클래스형 컴포넌트를 쓰면 staterender()함수와 같은 리액트가 미리 구현해 놓은 함수 쓸 수 있다.

클래스형 컴포넌트의 일생을 만들어 주는 생명주기 함수를 알아 본다.

 

 

constructor()함수

클래스형 컴포넌트 안에 constructor()함수 작성한다.

console.log()로 아무 문장이나 출력해보자. 

render()함수에도 console.log()로 아무 문장이나 출력해보자.

콘솔을 확인하면 constructor()함수  render()함수 

constructor()함수는 자바스크립트 함수이다.

 

함수의 실행 순서를 알면 리액트 앱을 만들 때 '언제 어디서 무슨 작업을 할 수 있을지' 결정할 수 있다.

 

 

componentDidMount()함수

componentDidMount()함수는 컴포넌트처음 화면에 그려지면 실행되는 함수이다.

컴퓨터에서 mount는 available한 상태로 준비한다는 뜻

 

함수를 작성하는 위치App 클래스 안이면 상관없다.

render()함수의 console.log()함수의 인자도 수정한다.

실행 순서 : render()함수 componentDidMount()함수

 

리액트에서 마운트(Mount)로 분류하는 생명주기 함수: constructor()함수, render()함수, componentDidMount()함수

 

생명주기 함수 실행 순서 : constructor()함수 render()함수 componentDidMount()함수

 

 

componentDidUpdate()함수

생명주기 함수 중 하나이다.

함수의 위치App 컴포넌트 안이면 상관없다.

componentDidUpdate()함수는 화면이 업데이트되면 (새로 그려지면) 실행된다.

<Add> <Minus> 버튼 눌러서 setState()함수를 실행시키는 경우 화면 업데이트된다.

setState()함수 실행되면 자동으로 render()함수 다시 실행된다.

 

실행 순서 : setState()함수 render()함수 componentDidUpdate()함수

 

 

componentWillUnmount()함수

컴포넌트가 죽을 때 언마운트(Unmount)라고 분류한다.

생명주기 함수이다.

함수의 위치 App 컴포넌트 안이면 상관없다.

이 함수는 컴포넌트가 화면에서 떠날 때 실행된다.

보통 컴포넌트에 적용한 이벤트 리스너를 제거할 때 많이 사용한다.

 

 

 


영화 앱 만들기 워밍업

생명주기 함수를 적용하여 Movie 컴포넌트를 구성해 보자.

 

App 컴포넌트 비우기

App 컴포넌트 깨끗하게 정리하자.

 

영화 앱 데이터 로딩하는 모습 상상해보면, 그런 상태를 구분해 줄 변수가 필요하다.

 

 

영화 데이터 로딩 상태 표시해 주기

isLoading state를 추가하자. 

isLoading state는 컴포넌트가 마운트되면 true여야 하므로 (처음에는 로딩 상태이므로)

 

 

isLoading state에 따라 '로딩중이다', '로딩이 다 됐다' 화면에 출력

구조 분해 할당삼항 연산자를 활용해서 로딩 상태 알려 주는 문장 출력한다.

삼항 연산자는 isLoading이 true이면 ? 다음 문장, false이면 : 다음 문장

 

브라우저를 보면 Loading..이라고 뜬다. (영화 데이터가 없는 상태도 로딩 상태로 간주한다.)

 

App 컴포넌트가 그려지면 (render()함수가 진행되면) 호출되는 생명주기 함수componentDidMount()함수이다.

이 함수에 setTimeout()함수적용해서 영화 데이터가 로딩되는 현상을 구현한다.

 

 

로딩 현상 구현하기

setTimeout()함수첫번째 인자전달한 함수{ }두번째 인자전달한 값 (밀리초) 후에 실행한다.

6초 후isLoading state를 false로 바꿔보자.

 

브라우저에서 6초 후에 Loading... 이라는 문장We are ready 라는 문장으로 바뀐다.

(6초 후에 isLoading state가 false가 되기 때문이다.)

 

다음은 영화 앱을 로딩해야 한다. 원래 자바스크립트의 fetch()함수를 알아야 하는데 대신 Axios도구 사용한다. (나중에)

 

 

영화 데이터 어디에 저장?

componentDidMount() 안에 영화 데이터가 로딩된다.

로딩된 영화 데이터는 state에 저장한다.

 

 

로딩된 영화 데이터를 저장할 수 있도록 movie state를 만들자

배열이다. 객체의 원소가 주루룩 들어온다.

 

state를 미리 계획해서 생성하면 좋은 코딩 습관을 가지게 된다.

나중에 setState()함수로 movies state에 데이터 추가해도 상관없다.

state = { isLoading: true };    처음에 없던 movie state를 

...(생략)....                          로딩 이후

this.setState( { isLoading: false,  movies: /*로딩된 영화 데이터...*/ } )   setState()로 추가해도 된다

하지만 좋지 않은 방법이다.

미리 데이터를 정의하기권장한다.