[React] 8. 자바스크립트 메서드 map

해롱그·2023년 11월 3일

react

목록 보기
9/14

map

map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다.

const array1 = [1, 4, 9, 16];

const map1 = array1.map((x) => x * 2);

console.log(map1);  // [ 2, 8, 18, 32 ]
arr.map(callback(currentValue[, index[, array]])[, thisArg])

매개변수 callback
새로운 배열 요소를 생성하는 함수. 다음 세 가지 인수를 가진다.
1. currentValue: 처리할 현재 요소
2. index: 처리할 현재 요소의 인덱스
3. array: map()을 호출한 배열

thisArg: callback을 실행할 때 this로 사용되는 값

반환 값
배열의 각 요소에 대해 실행한 callback의 결과를 모은 새로운 배열

map을 이용한 구현

map()을 사용하기 위해 배열을 하나 만들자.

import React from "react";

  const vegetables = ["감자", "고구마", "오이", "가지", "옥수수"];

  return (
    <div className="app-style">
      {vegetables.map((vegetableName) => {
        return (
          <div className="square-style" key={vegetableName}>
            {vegetableName}
          </div>
        );
      })}
    </div>
  );
};

export default App;

JSX 부분에서 map() 즉, 자바스크립트 코드를 작성할 것이기 때문에 { } 로 먼저 감싸고 시작한다.
JSX에서 map() 은 배열의 모든 요소를 순회한다. 그래서 클라이언트에서는 배열 형태의 데이터를 활용해서 화면을 그려주는 경우가 많고, 이때 배열의 값들로 동적으로 컴포넌트를 만들 수 있다.
map을 사용하니 중복된 코드가 사라지고 1개의 컴포넌트를 이용하면서 그 안에서 <div>{vegetableName}</div> 가 순차적으로 보여지고 있다.

import React from "react";
import "./App.css";

// User 컴포넌트를 분리해서 구현
function User({user}) {
  return (
    <div>{user.age}- {user.name}</div>
  );
}

function App() {
  // const vegetables = ["감자", "고구마", "오이", "가지", "옥수수"];
  const users = [
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" }
  ];
  return (
    <div className="app-container">
      {users.map((user) => {
        return <User user={user} key={user.id} />;
      })}
    </div>
  );
};

export default App;

User 컴포넌트에 props로 들어오는 user 정보인 {user}는 { id: 1, age: 30, name: "송중기" } 라는 정보가 들어온다.
이처럼 우리는 map()의 기능을 이용해서 반복되는 컴포넌트를 간단하게 화면에 표시할 수 있다.

이제 유저를 추가하고, 삭제하는 연습을 해보자

import React, { useState } from "react";
import "./App.css";

const User = ({ user }) => {
  return (
    <div>{user.age}- {user.name}</div>
  );
}

function App() {
    // useState를 이용한 상태값 만들기
  const [userList, setUserList] = useState([
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" }
  ]);
  // 유저의 입력값을 담을 상태
  const [name, setName] = useState('');
  const [age, setAge] = useState('');

  const addUSerHandler = () => {
    const newUser = {
      id: userList.length + 1,
      age: age,
      name: name
    };
    setUserList([...userList, newUser]);
  };

  return (
    <div className="app-container">
      <input value={name} placeholder="이름을 입력해주세요"
        onChange={(e) => setName(e.target.value)} />
      <input value={age} placeholder="나이를 입력해주세요"
        onChange={(e) => setAge(e.target.value)} />
      {userList.map((user) => {
        return <User user={user} key={user.id} />;
      })}
      <button onClick={addUSerHandler}>추가하기</button>
    </div>
  );
};

export default App;

input 박스와 유저의 입력값 담을 상태를 선언해주면 유저 추가 끝!

이제 유저 삭제를 해보자.

import React, { useState } from "react";
import "./App.css";

const User = (props) => {
  return (
    <div className="user-card">
      <div>{props.user.age}- {props.user.name}</div>
      <button onClick={() => props.handleDelete(props.user.id)}>
        삭제
      </button>
    </div>
  );
}

function App() {
    // useState를 이용한 상태값 만들기
  const [userList, setUserList] = useState([
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" }
  ]);
  // 유저의 입력값을 담을 상태
  const [name, setName] = useState('');
  const [age, setAge] = useState('');

  const addUSerHandler = () => {
    const newUser = {
      id: userList.length + 1,
      age: age,
      name: name
    };
    setUserList([...userList, newUser]);
  };

  const deleteUserHandler = (id) => {
    const newUserList = userList.filter(user => user.id !== id);
    setUserList(newUserList);
  };

  return (
    <div className="app-container">
      <input value={name} placeholder="이름을 입력해주세요"
        onChange={(e) => setName(e.target.value)} />
      <input value={age} placeholder="나이를 입력해주세요"
        onChange={(e) => setAge(e.target.value)} />
      {userList.map((user) => {
        return <User user={user} key={user.id}
          handleDelete={deleteUserHandler} />;
      })}
      <button onClick={addUSerHandler}>추가</button>
    </div>
  );
};

export default App;

컴포넌트 분리
버튼들이 많아졌으므로 계속 재사용하기 위해 버튼 컴포넌트로 분리해보자.
아래와 같이 컴포넌트를 따로 분리해주면, 추가하기 버튼은 초록색, 삭제하기 버튼은 빨강색으로 더 간편하게 표현할 수 있다.

import React, { useState } from "react";
import "./App.css";

// 버튼 컴포넌트 분리 (분리 시 CSS하기 더 편함)
function CustomButton(props) {
  const { color, onClick, children } = props
  
  if (color)
    return (
      <button
        style={{ background: color, color: "white" }}
        onClick={onClick}>
        {children}
      </button>
    );
  return <button onClick={onclick}>{props.children}</button>;
}

// User 컴포넌트 분리
const User = (props) => {
  return (
    <div className="user-card">
      <div>{props.user.age}- {props.user.name}</div>
      {/* 버튼 컴포넌트로 바꾸기 */}
      <CustomButton color="red" onClick={() => props.handleDelete(props.user.id)}>
        삭제
      </CustomButton>
    </div>
  );
}

function App() {
    // useState를 이용한 상태값 만들기
  const [userList, setUserList] = useState([
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" }
  ]);
  // 유저의 입력값을 담을 상태
  const [name, setName] = useState('');
  const [age, setAge] = useState('');

  const addUserHandler = () => {
    const newUser = {
      id: userList.length + 1,
      age: age,
      name: name
    };
    setUserList([...userList, newUser]);
  };

  const deleteUserHandler = (id) => {
    const newUserList = userList.filter(user => user.id !== id);
    setUserList(newUserList);
  };

  return (
    <div className="app-container">
      <input value={name} placeholder="이름을 입력해주세요"
        onChange={(e) => setName(e.target.value)} />
      <input value={age} placeholder="나이를 입력해주세요"
        onChange={(e) => setAge(e.target.value)} />
      {userList.map((user) => {
        return <User user={user} key={user.id}
          handleDelete={deleteUserHandler} />;
      })}
      {/* 버튼 컴포넌트로 바꾸기 */}
      <CustomButton color="green" onClick={addUserHandler}>추가</CustomButton>
    </div>
  );
};

export default App;

key

리액트에서 map을 사용하여 컴포넌트를 반복 렌더링 할 때는 반드시 컴포넌트에 key를 넣어줘야 한다. 넣지 않으면 오류가 발생할 수 있다.
key가 필요한 이유는 React에서 컴포넌트 배열을 렌더링했을 때 각각의 원소에서 변동이 있는지 알아내려고 사용하기 때문이다. 만약 key가 없다면 React는 가상돔을 비교하는 과정에서 배열을 순차적으로 비교하면서 변화를 감지하려고 한다. 하지만 key가 있으면 이 값을 이용해서 어떤 변화가 일어났는지 더 빠르게 알아낼 수 있게 된다.
즉, key값을 넣어줘야 React의 성능이 더 최적화된다.

map에서 조건식 사용하기

map() 안에서 조건식을 사용할 수 있다.
age가 25 미만인 user는 User 컴포넌트를 이용해 화면에 렌더링 해주고, 그것이 아닐 때는 화면에 아무것도 렌더링 하지 않기 위해 null 을 return한다.

동등연산자 & 일치연산자

동등 연산자(==)

두 피연산자의 값이 서로 같으면 true를 반환한다.
이때 두 피연산자의 타입이 서로 다르면, 비교를 위해 강제로 타입을 같게 변환한다.

일치 연산자(===)

타입의 변환 없이 두 피연산자의 값이 같고, 타입도 같아야만 true를 반환한다.

profile
사랑아 컴퓨터해 ~

0개의 댓글