React에서 배열 내장함수 map()과 filter() 사용해보기

binary·2022년 1월 24일
1
post-thumbnail

map()이 뭐지?

  • JavaScript의 표준 내장 객체이다.

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

참고 : MDN

const arr = [1, 2, 3, 4, 5] 라는 배열이 있다.

배열 안에 있는 모든 요소를 제곱하여 새로운 배열을 만들고 싶다면 어떻게 해야 할까?

바로 map() 메서드를 사용하면 된다.

const arr = [1, 2, 3, 4, 5];

const mapArr = arr.map(num => num * num);

console.log(arr);
// > Array [1, 2, 3, 4, 5]

console.log(mapArr);
// > Array [1, 4, 9, 16, 25]

map() 메서드 안에 들어가는 내용은 callback함수이다.

배열 arr에 있는 요소(num)들에 함수를 실행하고 나온 값(num * num)을 저장하여 새로운 배열(mapArr)로 만든다.

map() 활용하기

배열의 요소들을 화면에 그리도록 map() 을 활용해 볼 것이다.

  • App.js
import "./App.css";
import Test01 from "./07/Test01";

function App() {
  return (
    <div className='App'>
      <Test01 />
    </div>
  );
}

export default App;
  • Test01 함수 컴포넌트
import React from "react";

export default function Test01() {
  const todoList = [
    { taskName: "방 청소", finished: false },
    { taskName: "화장실 청소", finished: true },
  ];

  // map() 함수
  const todos = todoList.map((todo) => <div>{todo.taskName}</div>);
  return (
    <>
      <label>TO DO</label>
      {todos}
    </>
  );
}
  • Test01 클래스 컴포넌트
import React, { Component } from "react";

class Test01 extends Component {
  render() {
    const todoList = [
      { taskName: "방 청소", finished: false },
      { taskName: "화장실 청소", finished: true },
    ];

    // map() 함수
    const todos = todoList.map((todo) => <div>{todo.taskName}</div>);
  return (
    <>
      <label>TO DO</label>
      {todos}
    </>
    );
  }
}

export default Test01;

객체를 요소로 가진 todoList 라는 배열을 만들었다.

taskName 을 화면에 그리고 싶어, map() 함수를 사용했다.

const todos = todoList.map((todo) => <div>{todo.taskName}</div>);

todotaskName만 가져와 todos 라는 이름을 가진 컴포넌트가 map() 함수를 돌면서 출력될 것이다.

| 실행화면

만약 map()이 없었더라면?!

배열에서 일일이 꺼내기

  • Test02 함수 컴포넌트
import React from "react";

export default function Test02() {
  const todoList = [
    { taskName: "방 청소", finished: false },
    { taskName: "화장실 청소", finished: true },
  ];
  
  return (
    <>
      <label>TO DO</label>
      <div>{todoList[0].taskName}</div>
      <div>{todoList[1].taskName}</div>
    </>
  );
}
  • Test02 클래스 컴포넌트
import React, { Component } from "react";

class Test02 extends Component {
  render() {
    const todoList = [
      { taskName: "방 청소", finished: false },
      { taskName: "화장실 청소", finished: true },
    ];

  return (
    <>
      <label>TO DO</label>
      <div>{todoList[0].taskName}</div>
      <div>{todoList[1].taskName}</div>
    </>
    );
  }
}

export default Test02;

이렇게 일일이 todoList 배열의 요소들을 선택하여 꺼내주어야 한다.

위처럼 배열의 요소가 적다면 일일이 꺼내는 게 어려운 일은 아니겠지만,
만약 배열의 요소의 개수가 사용자에 의해 변한다거나 점점 많아질수록 일일이 꺼내기 어려워지며, 코드도 불필요하게 길어지게 될 것이다.

map()과 key

Warning: Each child in a list should have a unique "key" prop

map() 함수를 사용하면 콘솔창에 위와 같은 에러가 뜰 것이다.

대충 해석해보니 리스트에 유니크한 키 값이 없다는 것 같다.

React는 key Prop을 사용하여 컴포넌트와 DOM 요소 간의 관계를 생성한다.
이렇게 생성된 관계를 이용하여 컴포넌트 리렌더링 여부를 결정하는데,
불필요한 리렌더링을 방지하기 위해서 자식 컴포넌트마다 독립적인 key 값을 주어야 한다.

참고 블로그

key 값 주기

  • Test01 함수 컴포넌트
import React from "react";

export default function Test01() {
  const todoList = [
    { taskName: "방 청소", finished: false },
    { taskName: "화장실 청소", finished: true },
  ];

  return (
    <>
      {todoList.map((todo, i) => (
        <div key={`tl-${i}`}>{todo.taskName}</div>
      ))}
    </>
  );
}
  • Test01 클래스 컴포넌트
import React, { Component } from "react";

class Test01 extends Component {
  render() {
    const todoList = [
      { taskName: "방 청소", finished: false },
      { taskName: "화장실 청소", finished: true },
    ];

  return (
    <>
      {todoList.map((todo, i) => (
        <div key={`tl-${i}`}>{todo.taskName}</div>
      ))}
    </>
    );
  }
}

export default Test01;

map() 을 사용하여 각 컴포넌트에 배열의 index로 고유한 key 값 을 주었다.

그러나, 배열의 indexkey 값 으로 주는 것은 지양해야 한다.

배열의 요소들의 순서가 바뀌는 경우에는 배열 요소의 index 도 바뀌고, 컴포넌트마다 고유한 key 값 도 같이 바뀐다.
이러면 리액트는 리렌더링 해야하는 컴포넌트를 헷갈려 다른 컴포넌트를 리렌더링할 수도 있다.

key 값 은 전역적으로 고유할 필요는 없고, 형제 사이에서 고유해야 한다.

  • Test01 함수 컴포넌트
import React from "react";

export default function Test01() {
  const todoList = [
    { taskName: "방 청소", finished: false },
    { taskName: "화장실 청소", finished: true },
  ];

  return (
    <>
      {todoList.map((todo) => (
        <div key={todo.taskName}>{todo.taskName}</div>
      ))}
    </>
  );
}
  • Test01 클래스 컴포넌트
import React, { Component } from "react";

class Test01 extends Component {
  render() {
    const todoList = [
      { taskName: "방 청소", finished: false },
      { taskName: "화장실 청소", finished: true },
    ];

  return (
    <>
      {todoList.map((todo) => (
        <div key={todo.taskName}>{todo.taskName}</div>
      ))}
    </>
    );
  }
}

export default Test01;

그래서 한 번 taskNamekey 값 으로 주었다.

| 실행화면

콘솔에 있던 오류 창이 사라졌다!

filter()가 뭐지?

  • JavaScript의 표준 내장 객체이다.

  • filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.

참고 : MDN

filter() 활용하기

const todoList = [
  { taskName: "방 청소", finished: false },
  { taskName: "화장실 청소", finished: true },
];

위에서 만들었던 todoList 배열이다.

filter() 메서드를 활용하여 finishedfalse 인 것만 화면에 그리도록 해보려고 한다.

  • Test01 함수 컴포넌트
import React from "react";

export default function Test01() {
  const todoList = [
    { taskName: "방 청소", finished: false },
    { taskName: "화장실 청소", finished: true },
  ];

  return (
     <>
      {todoList
        .filter((todo) => todo.finished === false)
        .map((todo, i) => (
          <div key={todo.taskName}>{todo.taskName}</div>
        ))}
    </>
  );
}
  • Test01 클래스 컴포넌트
import React, { Component } from "react";

class Test01 extends Component {
  render() {
    const todoList = [
      { taskName: "방 청소", finished: false },
      { taskName: "화장실 청소", finished: true },
    ];

  return (
    <>
      {todoList
        .filter((todo) => todo.finished === false)
        .map((todo, i) => (
          <div key={todo.taskName}>{todo.taskName}</div>
        ))}
    </>
    );
  }
}

export default Test01;

| 실행화면

0개의 댓글