FrontEnd/React

[ React ] Component Recycle Method

ChatjihoiPT 2025. 4. 6. 23:57

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