공부블로그

리액트 6장. 컴포넌트 반복 본문

리액트/리액트를 다루는 기술

리액트 6장. 컴포넌트 반복

떠어영 2021. 1. 6. 18:28
<u1>
	<li>눈사람</li>
	<li>얼음</li>
	<li>눈</li>
	<li>바람</li>
</u1>

웹 애플리케이션을 만들다 보면 위와 같이 형태가 계속 반복되는 경우가 있다.

리액트에서 반복적인 내용을 효율적으로 보여주고 관리하는 방법에 대해서 알아보자.

 

6. 1 ) 자바스크립트 배열의 map( )함수

map( ) : 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 변환하고 새로운 배열을 생성한다.

 

6. 1. 1 ) 문법

arr.map( callback, [thisArg] )
  • callback: 새로운 배열 요소를 생성하는 함수로 3개의 파라미터를 받는다. ( currentValue: 현재 처리하고 있는 요소, index: 의 인덱스값, array: 현재 처리하고 있는 원본 배열 )

  • thisArg: callback함수 내부에서 사용할 this 레퍼런스

6. 1. 2 ) 예제

var numbers = [ 1, 2, 3, 4, 5];

var processed = numbers.map (function(num){
	return num*num;
});

ES6문법에서는 const키워드를 사용하고 function대신 화살표 함수를 쓴다.

const result = numbers.map(num=> num*num);

 

6. 2 ) 데이터 배열을 컴포넌트 배열로 변환하기

IterationSample. js

import React from "react";

const IterationSample = () => {
  const names = ["눈사람", "얼음", "눈", "바람"];
  const nameList = names.map((name) => <li>{name}</li>);
  //<li>...</li>JSX코드로 된 배열을 새로 생성한 후 nameList에 담는다.
  return <u1>{nameList}</u1>;
};
export default IterationSample;

JSX코드를 쓸 때는 위처럼 DOM요소를 써도 되고 컴포넌트를 사용해도 된다.

 

App. js

import React, { Component } from "react";
import IterationSample from "./IterationSample";

class App extends Component {
  render() {
    return <IterationSample />;
  }
}
export default App;

 

작성한 후 렌더링하면 출력은 되지만 'key' prop이 없다는 경고를 띄운다.

 

 

6. 3 ) key

리액트에서 key 컴포넌트는 배열을 렌더링했을 때 어떤 원소에 변동( 생성, 제거, 수정 )이 있었는지 알아내기 위해 사용한다.

 

6. 3. 1 ) key 설정

 

key값을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정한다.

그리고 key 값은 언제나 유일해야 하므로 데이터가 가진 고윳값을 key 값으로 설정해야 한다.

하지만 IterationSample 컴포넌트에는 고유 번호가 없기 때문에 map함수에 전달되는 콜백함수의 인수인 index값을 key로 사용한다.

 

IterationSample. js - key값

const nameList = names.map((name, index) => <li key ={index}>{name}</li>);

 

6. 4 ) 응용하기

지금까지 배운 개념을 응용하여 동적인 배열을 렌더링해보자.

  1. 초기 상태 렌더링하기 

  2. 데이터 추가 기능 구현하기

  3. 데이터 제거 기능 구현하기

IterationSample. js

import React, { useState } from "react";

const IterationSample = () => {
  /* 1. 초기 상태 렌더링 */
  const [names, setNames] = useState([
    //세 가지 상태(useState)를 사용
    { id: 1, text: "눈사람" }, // 1) 데이터 배열 name (객체로 이루어짐)
    { id: 2, text: "얼음" },
    { id: 3, text: "눈" },
    { id: 4, text: "바람" },
  ]);
  const [inputText, setInputText] = useState(""); // 2) 텍스트를 입력할 수 있는 input
  const [nextId, setNextId] = useState("5"); // 3) 새로운 항목을 추가할 때 사용할 id

  const onChange = (e) => setInputText(e.target.value); //onChange: 입력한 값을 inputText에 업데이트

  /* 2. 데이터 추가 기능 */
  const onClick = () => {
    const nextNames = names.concat({
      //nextNames: id는 nextId이고 text는 inputText인 새로운 name 배열
      id: nextId,
      text: inputText,
    });
    setNextId(nextId + 1); //nextId+1을 업데이트
    setNames(nextNames); //위에서 만든 배열을 업데이트
    setInputText(""); //inputText 초기화
  };

  /* 3. 데이터 제거 기능 */
  const onRemove = (id) => {
    const nextNames = names.filter((name) => name.id !== id);
    //배열 내장 함수 filter사용: 원하는 원소만 분류, 제외
    setNames(nextNames); //분류한 값은 다시 업데이트
  };

  const nameList = names.map((name) => (
    <li key={name.id} onDoubleClick={() => onRemove(name.id)}>
      {name.text}
    </li>
  ));

  return (
    <>
      <input value={inputText} onChange={onChange} />
      <button onClick={onClick}>추가</button>
      <u1>{nameList}</u1>
    </>
  );
};
export default IterationSample;

초기state 설정      1) id, text를 가진 객체 배열 name, name을 업데이트하는 setNames함수

                         2) inputText, setInputText함수 ( inputText는 input요소의 value이다. )

                         3) nextId, setNextId함수 

 

이벤트핸들링 설정 - onChange:  inputText업데이트

                         - onClick: names.concat 함수를 사용해 새로운 배열을 생성해 nextNames에 넣어주고,

                                      name업데이트, nextId +1 업데이트, inputText초기화

                         - onRemove: id를 인자로 받아 names.filter함수로 원하는 원소만 제거하고 name은 다시 업데이트

                           onDoubleClick={( )=> onRemove(name.id)}

 

 

 

이렇게 이번 장에서는 반복되는 데이터를 렌더링하는 방법을 배우고, 이를 응용해 유동적인 배열을 다루는 방법을 알아보았다.

상태 안에서 배열을 변형할 때는 concat, filter등의 배열 내장함수를 사용하여 새로운 배열을 만들어 사용해야 한다.