6단원. 반복되는 Component
리스트나 데이터셋을 기반으로 동일한 구조의 UI를 여러 개 렌더링
1. Map 함수
반복되는 컴포넌트를 렌더링
파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 그 결과로 새로운 배열을 생성
arr.map(callback, [thisArg])
const numbers = [1, 2, 3, 4, 5];
const result = numbers.map(num => num * num);
console.log(result);
2. 함수의 Parameter
• callback: 새로운 배열의 요소를 생성하는 함수로 파라미터는 다음 세 가지
1. currentValue: 현재 처리하고 있는 요소
2. index: 현재 처리하고 있는 요소의 index 값
3. array: 현재 처리하고 있는 원본 배열
• thisArg(선택 항목): callback 함수 내부에서 사용할 this 레퍼런스
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const nameList = names.map(name => <li>{name}</li>);
return <ul>{nameList}</ul>;
};
export default IterationSample;
3. Key
컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내는 것
- key 값은 언제나 유일해야 함
- key 값이 중복되지 않도록 유의
- 데이터가 가진 고윳값을 key 값으로 설정해야 함
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const namesList = names.map((name, index) => <li key={index}>{name}</li>);
return <ul>{namesList}</ul>;
};
export default IterationSample;
4. 데이터 추가 기능 구현
- 배열의 push 함수를 사용하지 않고 concat을 사용
( push 함수는 기존 배열 자체를 변경해 줌
, concat은 새로운 배열을 만들어 줌 )
- onClick 함수에서 새로운 항목을 추가할 때 객체의 id 값은 nextId를 사용하도록 하고, 클릭될 때마다 값이 1씩 올라가도록 구현
- button이 클릭될 때 기존의 input 내용을 비우는 것도 구현
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' }
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = e => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정하고
text: inputText
});
setNextId(nextId + 1); // nextId 값에 1을 더해 준다.
setNames(nextNames); // names 값을 업데이트한다.
setInputText(''); // inputText를 비운다.
};
const namesList = names.map(name => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
5. 데이터 제거 구현
- 불변성을 유지하면서 배열의 특정 항목을 지울 때는 배열의 내장 함수 filter를 사용
- filter 함수의 인자에 분류하고 싶은 조건을 반환하는 함수를 넣어 주면 쉽게 분류
( 특정 배열에서 특정 원소만 제외시킬 수도 있음 )
상태 안에서 배열을 변형할 때는 배열에 직접 접근하여 수정하는 것이 아니라 concat, filter 등의 배열 내장 함수를 사용하여 새로운 배열을 만든 후 이를 새로운 상태로 설정해 주어야 함
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' }
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = e => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정하고
text: inputText
});
setNextId(nextId + 1); // nextId 값에 1을 더해 준다.
setNames(nextNames); // names 값을 업데이트한다.
setInputText(''); // inputText를 비운다.
};
const onRemove = id => {
const nextNames = names.filter(name => name.id != = id);
setNames(nextNames);
};
const namesList = names.map(name => (
<li key={name.id} onDoubleClick={() => onRemove(name.id)}>
{name.text}
</li>
));
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
7단원. Component Recycle
구조는 같지만 데이터나 스타일이 다른 UI를 효율적으로 구성하는 방식
1. 라이프사이클
- 마운트, 업데이크, 언마운트
- Will 접두사가 붙은 메서드는 어떤 작업을 작동하기 전에 실행되는 메서드
- Did 접두사가 붙은 메서드는 어떤 작업을 작동한 후에 실행되는 메서드

1.1 마운트
DOM이 생성되고 웹 브라우저상에 나타나는 것
• constructor: 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드
• getDerivedStateFromProps: props에 있는 값을 state에 넣을 때 사용하는 메서드
• render: 우리가 준비한 UI를 렌더링하는 메서드
• componentDidMount: 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메서드
1.2 업데이트
- props가 바뀔 때
- state가 바뀔 때
- 부모 컴포넌트가 리렌더링될 때
- this.forceUpdate로 강제로 렌더링을 트리거할 때

• getDerivedStateFromProps
이 메서드는 마운트 과정에서도 호출되며, 업데이트가 시작하기 전에도 호출됩니다. props의 변화에 따라 state 값에도 변화를 주고 싶을 때 사용합니다.
• shouldComponentUpdate
컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드입니다. 이 메서드에서는 true 혹은 false 값을 반환해야 하며, true를 반환하면 다음 라이프사이클 메서드를 계속 실행하고, false를 반환하면 작업을 중지합니다. 즉, 컴포넌트가 리렌더링되지 않습니다. 만약 특정 함수에서 this.forceUpdate() 함수를 호출한다면 이 과정을 생략하고 바로 render 함수를 호출합니다.
• render
컴포넌트를 리렌더링합니다.
• getSnapshotBeforeUpdate
컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드입니다.
컴포넌트의 업데이트 작업이 끝난 후 호출하는 메서드입니다.
1.3 언마운트
컴포넌트를 Dmo에서 제거하는 것(마운트의 반대과정)
• componentWillUnmount: 컴포넌트가 웹 브라우저상에서 사라지기 전에 호출하는 메서드
2. 라이프사이클 메서드
포넌트가 "태어나고(마운트), 자라고(업데이트), 사라지는(언마운트)" 전 과정에서 실행되는 특별한 함수들
2.1 render() 함수
라이프사이클의 유일한 필수 메서드
- 이 메서드 안에 this.props와 this.state에 접근할 수 있으며 리엑트 요소를 반환함
- event 설정이 아닌 곳에서 setState를 사용하면 안 되며, 브라우저의 DOM에 접근해서도 안 됨
- DOM 정보를 가져오거나 state에 변화를 줄 때는 componentDidMount에서 처리해야 함
2.2 constructor 매서드
컴포넌트의 생성자 메서드로 컴포넌트를 만들 때 처음으로 실행됨
constructor(props){...}
2.3 getDerivedStateFromProps 메서드
props로 받아 온 값을 state에 동기화시키는 용도로 사용
컴포넌트가 마운트될 때와 업데이트될 때 호출
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.value != = prevState.value) { // 조건에 따라 특정 값 동기화
return { value: nextProps.value };
}
return null; // state를 변경할 필요가 없다면 null을 반환
}
2.4 ComponentDidMount 메서드
컴포넌트를 만들고, 첫 렌더링을 다 마친 후 실행
이 안에서 다른 자바스크립트 라이브러리 또는 프레임워크의 함수를 호출하거나 이벤트 등록, setTimeout, setInterval, 네트워크 요청 같은 비동기 작업을 처리
componentDidMount() { ... }
2.5 shouldComponentUpdate 메서드
props 또는 state를 변경했을 때, 리렌더링을 시작할지 여부를 지정하는 메서드
반드시true값 또는false값을 반환해야함( 컴포넌트 생성 시 이 메서드를 따로 생성하지 않는다면 기본적으로 언제나 true 반환)
2.6 getSnapshotBeforeUpdate 메서드
render에서 만들어진 결과물이 브라우저에 실제로 반영되기 직전에 호출
주로 업데이트하기 직전의 값을 참고할 일이 있을 때 활용
getSnapshotBeforeUpdate(prevProps, prevState) {
if(prevState.array != = this.state.array) {
const { scrollTop, scrollHeight } = this.list
return { scrollTop, scrollHeight };
}
}
2.7 componentDidUpdate
리렌더링을 완료한 후 실행
DOM이 업데이트된 이후에 호출되므로 DOM 조작, API 호출 등 안전하게 가능함
componentDidUpdate(prevProps, prevState, snapshot) { ... }
2.8 componentWillUnmount 메서드
컴포넌트를 DOM에서 제거할 때 실행
componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM이 있다면 여기서 제거 작업을 해야 함
componentWillUnmount() { ... }
2.9 componentDidCatch 메서드
컴포넌트 렌더링 도중에 에러가 발생했을 때 애플리케이션이 먹통이 되지 않고 오류 UI를 보여 줄 수 있게 해줌
error는 파라미터에 어떤 에러가 발생했는지 알려 주며, info 파라미터는 어디에 있는 코드에서 오류가 발생했는지에 대한 정보를 줌
3. 라이프사이클 메서드 사용하기

import React, { Component } from 'react';
class LifeCycleSample extends Component {
state = {
number: 0,
color: null,
}
myRef = null; // ref를 설정할 부분
constructor(props) {
super(props);
console.log('constructor');
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log('getDerivedStateFromProps');
if(nextProps.color != = prevState.color) {
return { color: nextProps.color };
}
return null;
}
componentDidMount() {
console.log('componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate', nextProps, nextState);
// 숫자의 마지막 자리가 4면 리렌더링하지 않습니다.
return nextState.number % 10 != = 4;
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
handleClick = () => {
this.setState({
number: this.state.number + 1
});
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
if(prevProps.color != = this.props.color) {
return this.myRef.style.color;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate', prevProps, prevState);
if(snapshot) {
console.log('업데이트되기 직전 색상: ', snapshot);
}
}
render() {
console.log('render');
const style = {
color: this.props.color
};
return (
<div>
<h1 style={style} ref={ref => this.myRef=ref}>
{this.state.number}
</h1>
<p>color: {this.state.color}</p>
<button onClick={this.handleClick}>
더하기
</button>
</div>
)
}
}
export default LifeCycleSample;'FrontEnd > React' 카테고리의 다른 글
| [ React ] 컴포넌트 스타일링 (0) | 2025.04.08 |
|---|---|
| [ React ] Hook (1) | 2025.04.07 |
| [ React ] Element handling & Dom (0) | 2025.04.03 |
| [ React ] JSX Component & Props & State (1) | 2025.04.02 |
| [ React ] JSX (0) | 2025.04.01 |