재활용 가능한 UI 구성 단위
재활용하여 사용할 수 있다.
코드 유지보수에 좋다.
해당 페이지가 어떻게 구성되어 있는지 한 눈에 파악하기 좋다.
컴포넌트는 또 다른 컴포넌트를 포함할 수 있다. (부모 컴포넌트 - 자식 컴포넌트)
import React, {Component} from 'react';
class App extends Component {
render() {
const name = 'react';
return <div className="react">{name}</div>
}
}
export default App;
클래스형 컴포넌트에 비해서 훨씬 간단하고 단순하지만 state를 관리하지 못한다는 단점으로 인해 잘 사용되지 않았습니다.
하지만 React 16.8 버전에서 Hook 기능이 추가되면서 함수형 컴포넌트에서도 state를 사용할 수 있게 되었고 그 후부터 클래스형 컴포넌트보다는 함수형 컴포넌트가 더 많이 사용되기 시작했습니다.
import React from 'react';
import './App.css';
function App() {
const name = 'react';
return <div className = "react">{name}</div>
}
export default App;
React에서 컴포넌트는 여러 종류의 "생명주기 메소드" 를 가지며 이 메소드를 오버라이딩(상속하여 재정의) 하여 특정 시점에 코드가 실행되도록 설정 합니다.
클래스 컴포넌트에만 해당되는 내용이며, 함수형 컴포넌트는 Hook를 사용하여 생명주기에 원하는 동작을 합니다
컴포넌트가 인스턴스로 생성되고 DOM 트리에 삽입되어 브라우저상에 나타나는 과정
컴포넌트 props 또는 state가 바뀌었을 때
static getDerivedStateFromProps : Mounting 에서 등장한 메서드로 컴포넌트 props나 state가 바뀌는 등 업데이트 할 때도 호출됩니다.
shouldComponentUpdate
시점 : props 또는 state가 새로운 값으로 갱신되어 렌더링이 발생하기 직전에 호출
사용이유 : 성능(컴포넌트)최적화를 위해 사용한다. 컴포넌트가 리렌더링을 할지 말지 결정하는 메소드이다.
(함수형 컴포넌트에선 React.memo가 같은 역할을 한다.)
리액트 공식 홈페이지에서는 이 메소드 대신 PureComponent를 사용하는 것이 좋다고 한다.
shouldComponentUpdate(nextProps, nextState) {
// return false 하면 업데이트를 안함
return true;
// 기본값으로는 true를 반환
}
render : Mounting 에서 등장한 메서드로 업데이트에서도 호출됩니다.
getSnapshotBeforeUpdate
시점 : render 메서드 호출 후 브라우저에 나타나기 바로 직전에 호출되는 메서드이다.( 렌더링 결과가 실제 DOM에 반영 되기 직전에 호출 )
(render() -> getSnapshotBeforeUpdate -> DOM에 변화 반영 -> componentDidUpdate)
사용이유 : 브라우저에 그리기 전에 스크롤의 위치, DOM의 크기를 사전에 알고 싶을 때, 업데이트 되기 직전에 DOM 함수를 return 시켜가지고 그 return된 값을 componentDidUpdate에서 받을 수 있다
(메서드가 호출되는 시점에 이전 돔 요소의 상태값을 가져오기 좋다.)
이 메소드는 사용할 일이 별로 없지만 Hook에서 대체할 수 있는 기능이 아직 없다고 합니다.
예제) codesandbox.io/s/484zvr87ow?file=/src/index.js 참고
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevProps.color !== this.props.color) {
return this.myRef.style.color;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot) {
console.log("업데이트 되기 직전 색상: ", snapshot);
}
}
3번째 파라미터로 getSnapshotBeforeUpdate에서 반환한 값을 조회 할 수 있습니다.
컴포넌트가 브라우저상에서 사라질때
💡 해당 함수형 컴포넌트에서는 이전 클래스 컴포넌트와 비교하여 설명하자면, 클래스형 컴포넌트의 라이프사이클 메서드로 사용되었던 constructor(), render(), ComponenDidMount(), componentDidUpdate(), componentWillUnmount()는 함수형 컴포넌트에서 아래와 같이 사용을 하고 있습니다.
💡[ 생명주기 순서 요약 ]
1. 함수형 컴포넌트가 호출이 됩니다.
2. 함수형 컴포넌트의 내부에서 실행합니다.
3. return()으로 화면에 렌더링 합니다.
4. useEffect()가 실행됩니다.
💡 [ 조건부 수행 ]
1. 변경 혹은 컴포넌트의 소멸이 발생 시 useEffect() 실행
💡 [더 알아보기]
1. 렌더링(Rendering) 이란?
React 내에서는 컴포넌트 렌더링이라고도 하며, 컴포넌트 내에 엘리먼트 요소들(HTML, React 사용자 정의 태그)을 화면상에 그리는 동작을 의미한다.
2. 리 렌더링(re-Rendering) 이란?
컴포넌트 내에 엘리먼트 요소들을 코드를 기반으로 화면의 그리는 작업을 다시 수행하는 것을 의미한다.
💡 컴포넌트가 호출이 되었을 때 가장 먼저 호출이 되는 것은 컴포넌트 내부입니다. 라이프 사이클 메서드라고 할 수는 없지만 클래스 컴포넌트의 constructor()를 이해하기 위해 설명합니다. 동일하게 State를 정의하거나 사용될 함수들에 대해서 미리 정의를 하는 공간입니다.
/**
* 함수형 컴포넌트 예시
*/
const LifecycleFunctionComponent: React.FC = (props: any) => {
/**
* 컴포넌트 호출 시 가장 먼저 호출이 되는 공간
* 컴포넌트에서 사용 될 state나 함수들을 정의 하는 공간입니다.
*/
console.log("해당 부분이 제일 먼저 호출이 됩니다.");
const [userInfo, setUserInfo] = useState<any>({
userId: 'adjh54',
userAge: 50,
isShowTempComponent: false,
});
return (
<></>
)
};
export default LifecycleFunctionComponent;
💡 미리 구현한 HTML를 화면상에 보여주는 메서드입니다.
import React, { useEffect, useState } from "react";
/**
* 함수형 컴포넌트 예시
*/
const LifecycleFunctionComponent: React.FC = (props: any) => {
const [userInfo, setUserInfo] = useState<any>({
userId: 'adjh54',
userAge: 50,
isShowTempComponent: false,
});
/**
* 미리 구현한 HTML를 화면상에 보여주는 메서드이다.
*/
return (
<>
{console.log("Renering ...")}
<div>
<h1>Main Function Component 입니다.</h1>
<div>{userInfo.userAge}</div>
</div>
</>
);
};
export default LifecycleFunctionComponent;
해당 메서드를 통하여서 Mounting/Updating/Unmounting 처리가 가능합니다.
하나의 컴포넌트 내에서 여러 개 선언이 가능하며, 하나의 메서드로 처리를 해도 무방합니다.
[ 메서드 구조 ]
useEffect( function, deps? );
- function : useEffect가 수행될 때 실행되는 함수
- deps [optional] : 배열 형태이며, 의존(dependency) 값을 의미한다.
💡 컴포넌트 내에서 렌더링이 수행된 이후에 실행이 되는 메서드이다.
deps 파라미터를 빈 배열로 수행하면 렌더링이 수행된 이후 최초 한번 수행이 된다.
import React, { useEffect, useState } from "react";
import { LifecycleType } from "./LifecycleType";
/**
* 함수형 컴포넌트 예시
*/
const LifecycleFunctionComponent: React.FC = (props: any) => {
/**
* 1. 컴포넌트 호출 시 가장 먼저 호출이 되는 공간
* 컴포넌트에서 사용 될 state나 함수들을 정의 하는 공간입니다.
*/
console.log("해당 부분이 제일 먼저 호출이 됩니다.");
const [userInfo, setUserInfo] = useState<LifecycleType>({
userId: 'adjh54',
userAge: 50,
isShowTempComponent: false,
});
/**
* 3. 컴포넌트 내에서 렌더링이 수행된 이후에 실행이 되는 메서드이다.
* @returns {void}
*/
useEffect(() => {
console.log("화면이 렌더링 된 이후에 바로 수행이 됨: componentDidMount()과 동일");
}, []);
/**
* 2. 미리 구현한 HTML(JSX)를 화면상에 보여주는 메서드이다.
*/
return (
<>
{console.log("Renering ...")}
<div>
<h1>Main Function Component 입니다.</h1>
<div>{userInfo.userAge}</div>
</div>
</>
);
};
export default LifecycleFunctionComponent;
💡 컴포넌트 내에서 변화가 발생하였을 경우에 실행되는 메서드이다.
import React, { useEffect, useState } from "react";
import { LifecycleType } from "./LifecycleType";
/**
* 함수형 컴포넌트 예시
*/
const LifecycleFunctionComponent: React.FC = (props: any) => {
/**
* 컴포넌트 호출 시 가장 먼저 호출이 되는 공간
* 컴포넌트에서 사용 될 state나 함수들을 정의 하는 공간입니다.
*/
console.log("해당 부분이 제일 먼저 호출이 됩니다.");
const [userInfo, setUserInfo] = useState<LifecycleType>({
userId: 'adjh54',
userAge: 50,
isShowTempComponent: false,
});
/**
* 컴포넌트 내에서 변화가 발생하였을 경우에 실행되는 메서드이다.
*/
useEffect(() => {
console.log("전달 받은 props의 값에 변화가 생겼을 경우 / 사용자 나이의 변화가 발생하였을 경우 수행이 된다. : componentDidUpdate()와 동일");
}, [props.appState, userInfo.userAge]);
/**
* 미리 구현한 HTML(JSX)를 화면상에 보여주는 메서드이다.
*/
return (
<>
{console.log("Renering ...")}
<div>
<h1>Main Function Component 입니다.</h1>
<div>{userInfo.userAge}</div>
</div>
</>
);
};
export default LifecycleFunctionComponent;
💡 컴포넌트 내에서 DOM을 제거할 때에 실행이 되는 메서드이다.
💡 LifeCycleFunctionComponent이라는 컴포넌트에서 LifeCycleUnmountComponent라는 컴포넌트를 화면상에 보여주고 있습니다. 버튼을 눌렀을 경우 해당 컴포넌트가 제외될 때, LifeCycleUnmountComponent 컴포넌트의 'useEffect()'가 수행되는 것을 확인할 수 있습니다.
import React, { useEffect, useState } from "react";
import { LifecycleType } from "../../type/lifecycle/LifecycleType";
/**
* 함수형 컴포넌트 예시
*/
const LifeCycleFunctionComponent: React.FC = (props: any) => {
const [isShowTempComp, setIsSHowTempComp] = useState<boolean>(true);
/**
* 컴포넌트 호출 시 가장 먼저 호출이 되는 공간
* 컴포넌트에서 사용 될 state나 함수들을 정의 하는 공간입니다.
*/
console.log("해당 부분이 제일 먼저 호출이 됩니다.");
const [userInfo, setUserInfo] = useState<LifecycleType>({
userId: 'adjh54',
userAge: 50,
isShowTempComponent: false,
});
/**
* 임시 컴포넌트 Unmount
*/
const fn_unmountCompoent = () => {
setIsSHowTempComp(!isShowTempComp);
}
/**
* 미리 구현한 HTML(JSX)를 화면상에 보여주는 메서드이다.
*/
return (
<>
{console.log("Renering ...")}
<div>
<h1>Main Function Component 입니다.</h1>
<button onClick={fn_unmountCompoent}>컴포넌트 제거</button>
{
isShowTempComp && (
<LifeCycleUnmountComponent />
)
}
</div>
</>
);
};
export default LifeCycleFunctionComponent;
const LifeCycleUnmountComponent = () => {
useEffect(() => {
return () => {
console.log("LifeCycleUnmountComponent가 Unmount 되었습니다.")
}
}, []);
return (
<div>
<h1> Unmount Component</h1>
</div>
)
}
JavaScript Syntax Extension. 리액트에서 사용하는 자바스크립트 확장 문법. JSX로 작성한 코드는 브라우저에서 동작하는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환됩니다.
HTML 태그를 그대로 사용하기 때문에 보기 쉽고 익숙합니다.
HTML 태그를 사용하는 동시에 자바스크립트도 JSX 안에서 동작하게 할 수 있습니다.
vs. DOM + Event
<div style={{color : "red"}}>
Hello React</div>Hello React</div>
<div></div> vs. <div />
<> ... </>
)<>
<div className="loginBtn" onClick={() => console.log("click")}>Login</div>
<br />
<div style={{backgroundColor: "grey", height: "10px"}} />
</>
참고
https://velog.io/@sdc337dc/0.%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8
https://born-dev.tistory.com/m/27
https://velog.io/@seong-dodo/React-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-vs-%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8
https://adjh54.tistory.com/m/43