React 8. component 반복 - map()

rachel's blog·2021년 10월 30일
1

React

목록 보기
9/13
post-thumbnail

반복되는 코드의 경우 컴포넌트화 하기 위해 배열의 내장 함수인 map함수를 사용해서 랜더링 할 수 있다.

array.map(콜백함수, thisArg)

  • 콜백 함수
    -currentValue : 현재 요소
    -index : currentValue의 인덱스 값
    -array: 현재 처리하고 있는 원본 배열
  • thisArg : 콜백함수 내부에서 사용할 this
import React, { Component } from 'react'

class IterationSample extends Component {
   render() {
       return (
           <ul>
              <li>눈사람</li> 
              <li>얼음</li> 
              <li></li> 
              <li>바람</li> 
              <li>엘겨울</li> 
           </ul>
       )
   }
}

export default IterationSample

⬇클래스형 컴포넌트로 map()함수를 이용해서 반복되는 코드를 간결화

import React, { Component } from "react";

class IterationSample extends Component {
 state = {
   names: ["눈사람", "얼음", "눈", "바람"],
 };
 render() {
   return (
     <ul>
       {this.state.names.map((name, index) => {
         return <li key={index}>{name}</li>;
       })}
     </ul>
   );
 }
}

export default IterationSample;

💡 key 값을 설정해 주어야 하는 이유?

리액트에서 key의 역할은 배열을 랜더링했을 떄, 리스트를 순차적으로 비교하면서 변화를 감지하는 속도를 높이는 것이다. 데이터의 고유값을 식별하는 역할이므로 언제가 유일해야 한다.

  • 이 때, 데이터가 가진 고유의 값이 없을 때만 index를 사용하고 그 외의 경우에는 해당 데이터의 고유값(ex. id)를 사용한다.
  • index를 key로 사용할 경우 리랜더링이 비효율적이다.

예제

step 1. 초기 상태 설정

import React, { Component } from "react";

class IterationSample extends Component {
  state = {
    names: [
      { id: 1, text: "눈사람" },
      { id: 2, text: "얼음" },
      { id: 3, text: "눈" },
      { id: 4, text: "바람" },
    ],
    inputText: "",
    newxId: 5,
  };
  render() {
    return (
      <ul>
        {this.state.names.map((name) => {
          return <li key={name.id}>{name.text}</li>;
        })}
      </ul>
    );
  }
}

export default IterationSample;

클래스형 컴포넌트 사용,
key값을 index 대신 name의 id값(name.id)로 설정

step 2. 데이터 추가하기

import React, { Component } from "react";

class IterationSample extends Component {
  state = {
    names: [
      { id: 1, text: "눈사람" },
      { id: 2, text: "얼음" },
      { id: 3, text: "눈" },
      { id: 4, text: "바람" },
    ],
    inputText: "",
    nextId: 5,
  };
  handleChange = (e) => {
    this.setState({
      inputText: e.target.value,
    });
  };
  handleAddTextButton = () => {
    this.setState({
      names: [...this.state.names].concat({
        id: this.state.nextId,
        text: this.state.inputText,
      }),
      inputText: "",
      nextId: this.state.nextId + 1,
    });
  };
  render() {
    const { names } = this.state;
    return (
      <>
        <input
          type="text"
          value={this.state.inputText}
          onChange={this.handleChange}
        />
        <button onClick={this.handleAddTextButton}>추가</button>
        <ul>
          {names.map((name) => (
            <li key={name.id}>{name.text}</li>
          ))}
        </ul>
      </>
    );
  }
}

export default IterationSample;

배열 항목 추가시 push가 아닌 concat 사용 : push는 원본배열을 자체를 변경, concat은 새로운 배열을 만들어준다
➡ 원본 배열 자체를 수정하는 메서드를 사용할때에는 원본 값이 변경되므로 주의해서 사용하거나, 미리 원본을 다른 변수에 넣어 놓아야 한다.
(참고 : 원본 배열 자체를 변경하는 메서드 : push(), unshift(), shift(), pop()
리액트에서는 상태를 업데이트 할 때 기존 상태를 그대로 두면서 새로운 값을 설정해야 함!(불변성 유지 → 컴포넌트 최적화)

step 3. 데이터 제거하기

import React, { Component } from "react";

class IterationSample extends Component {
  state = {
    names: [
      { id: 1, text: "눈사람" },
      { id: 2, text: "얼음" },
      { id: 3, text: "눈" },
      { id: 4, text: "바람" },
    ],
    inputText: "",
    nextId: 5,
  };
  handleChange = (e) => {
    this.setState({
      inputText: e.target.value,
    });
  };
  handleAddTextButton = () => {
    this.setState({
      names: [...this.state.names].concat({
        id: this.state.nextId,
        text: this.state.inputText,
      }),
      inputText: "",
      nextId: this.state.nextId + 1,
    });
  };
  removeText = (id) => {
    const { names } = this.state;
    this.setState({
      names: names.filter((name) => name.id !== id),
    });
  };
  render() {
    const { names } = this.state;

    return (
      <>
        <input
          type="text"
          value={this.state.inputText}
          onChange={this.handleChange}
        />
        <button onClick={this.handleAddTextButton}>추가</button>
        <ul>
          {names.map((name) => (
            <li key={name.id} onDoubleClick={() => this.removeText(name.id)}>
              {name.text}
            </li>
          ))}
        </ul>
      </>
    );
  }
}

export default IterationSample;

배열의 내장 함수 filter 사용 : 불변성 유지
필터링해서 특정 조건을 만족하는 데이터만 새로운 배열로 반환한다.
onRemove() 활용해서 내가 클릭한 li만 없애주기 구현

profile
블로그 이전 : https://rachelslab.tistory.com/

0개의 댓글