상세 컨텐츠

본문 제목

[리액트] map : 많은 div들을 반복문으로 줄이고 싶은 충동이 들 때

리액트

by front-hyun 2023. 8. 30. 14:06

본문

똑같은 html이 반복적으로 출현하면

반복문을 이용해서 쉽게 똑같은 html을 생성할 수도 있습니다. 

안타깝게도 for 반복문은 JSX 중괄호 안에서 사용할 수 없어서 map() 을 대신 사용합니다. 

 

 

 

 

자바스크립트 map 함수 쓰는 법 

 

모든 array 자료 우측엔 map() 함수를 붙일 수 있습니다. 

자바스크립트 기본함수 같은건데 용도를 알아봅시다. 

map 함수는 JSX 문법이어서 return문 안에 사용할 수 있는데 쓸 때 { } 내부에 써야 합니다. !!!

map이 쓰기 싫다면 for문 써도 되지만 return문 밖에 써야 한다는 점 !

 

var 어레이 = [2,3,4];
어레이.map(function(){
  console.log(1)
});

기능 1. array에 들어있는 자료갯수만큼 그 안에 있는 코드를 반복실행해줍니다.

저러면 진짜로 console.log(1) 3번 실행됨 

 

 

 

var 어레이 = [2,3,4];
어레이.map(function(a){
  console.log(a)
});

기능 2. 콜백함수에 파라미터 아무렇게나 작명하면

그 파라미터는 어레이 안에 있던 모든 자료를 하나씩 출력해줍니다.

(그냥 소괄호안에 있는 함수를 콜백함수라고 합니다)

저러면 진짜로 2, 3, 4가 콘솔창에 출력됨 

 

 

 

var 어레이 = [2,3,4];
var newArray = 어레이.map(function(a){
  return a * 10
});
console.log(newArray)

기능3. return 오른쪽에 뭐 적으면 array로 담아줍니다.

그리고 map() 쓴 자리에 남겨줍니다.

그래서 변수에 담아서 출력해봤더니 진짜로 array에 담아주긴 하는군요 

newArray는 [20, 30, 40] 이 출력됩니다. 

 

 

 

 

 

 

 

 

JSX 안에서 html을 반복생성하고 싶으면

 

리액트 중괄호안에서 html을 반복생성하고 싶으면 아까 배운 map을 이용해도 됩니다. 

 

 

function App (){
  return (
    <div>
      { 
        [1,2,3].map(function(){
          return ( <div>안녕</div> )
        }) 
      }
    </div>
  )
}

▲ 이렇게 쓰면 <div>안녕</div> 이 3개나 생성됩니다.

진짜인지 미리보기화면에서 확인해봅시다.

 

 

 

 

 

 

 

 

 

예전에 만들었던 글제목 3개도 반복문으로 축약 가능할듯

 

지금 우리 프로젝트를 잘 보면

<div className="list"> 이 부분이 3번이나 반복되고 있습니다.

이것도 map 반복문으로 축약하면 코드 양이 더 줄어들지 않을까요. 

실제 블로그 글갯수만큼 html 생성해주세요~

 

 

function App (){
  return (
    <div>
      (생략)
      { 
        글제목.map(function(){
          return (
          <div className="list">
            <h4>{ 글제목[0] }</h4>
            <p>2월 18일 발행</p>
          </div> )
        }) 
      }
    </div>
  )
}

▲ 이렇게 하면 글제목이 3개 생성됩니다. 

(글제목이라는 state도 array자료라서 map 붙일 수 있습니다)

 

  let [글제목, 글제목변경]=useState(['남자 코트 추천','강남 우동맛집','파이썬 독학']);
 

글제목은 [ ] array니깐 map 함수 사용 가능 !!! -> return 내의 값을 3번 반복해서 출력해줌. why? array 내의 값 개수가 3개니깐

 

그래서 오늘의 결론은

비슷한 html 여러개 필요하면 map() 안에 담으면 됩니다. 

 

 

 

 

 

 

 

 

 

 

근데 반복된 HTML에 각각 다른 제목을 부여하고 싶다면

 

지금 위의 코드를 잘 보시면 <h4>{ 글제목[0] }</h4> 이라는 것만 3번 반복되고 있습니다. 

그래서 같은 제목만 3번 출현하는듯요

 

그게 아니라 반복문이 돌 때마다

<h4>{ 글제목[0] }</h4>

<h4>{ 글제목[1] }</h4>

<h4>{ 글제목[2] }</h4>

이런 데이터가 들어가게 만들고 싶으면 어떻게 코드를 수정해야할까요?

그것은 아까 map 함수의 사용법을 잘 상기시켜보면 알 수 있습니다.

 

 

 

 

function App (){
  return (
    <div>
      (생략)
      { 
        글제목.map(function(a){
          return (
          <div className="list">
            <h4>{ a }</h4>
            <p>2월 18일 발행</p>
          </div> )
        }) 
      }
    </div>
  )
}

▲ 이렇게 하면 각각 다른 글제목이 3개 생성됩니다. 성공 

 

a 파라미터는 반복문 돌 때마다 array 안에 있던 데이터랬음 !!

a는 배열 내의 데이터라면 두번째 파라미터인 i는 반복문 돌때마다 1씩 증가하는 인덱스이다. 0, 1, 2 ... 따라서 <h4>안에 array 세개를 다 출력하고 싶다면? 글제목[i] / a 둘 중 하나 쓰면 됩니다 !~~~

 

 

 

 

function App (){
  return (
    <div>
      (생략)
      { 
        글제목.map(function(a, i){
          return (
          <div className="list">
            <h4>{ 글제목[i] }</h4>
            <p>2월 18일 발행</p>
          </div> )
        }) 
      }
    </div>
  )
}

▲ 실은 이렇게 해도 되는데 왜냐면 

map(function(a, i){

이렇게 파라미터를 2개까지 작명 가능한데

첫째 파라미터 a는 array안에 있던 자료

둘째 파라미터 i는 0부터 1씩 증가하는 정수

가 되어서 그렇습니다.

i 출력해보면 0 1 2 이런 식으로 나옵니다. 진짜임  

 

 

 

결론: 비슷한 html 반복생성하려면 map() 쓰면 된다. 

 

 

 

 

전에 만들었던 따봉기능도 추가해보면

 

 

function App (){
  return (
    <div>
      (생략)
      { 
        글제목.map(function(a, i){
          return (
          <div className="list">
            <h4 onClick={()=>{ 따봉변경(따봉+1) }}>{ 글제목[i] }</h4>
            <p>2월 18일 발행</p>
          </div> )
        }) 
      }
    </div>
  )
}

▲ 반복문 안에 있는 html에 onClick 같은거 추가해도 아무런 문제가 없습니다.

근데 약간 문제가 있는데

아무 글제목이나 클릭하면 따봉갯수가 다 똑같이 증가하는군요

그게 싫으면 오늘 숙제로 해결해봅시다. 

 

(참고) map 반복문으로 반복생성한 html엔 key={i} 이런 속성을 추가해야합니다. 

 

<div className="list" key={i}> 

그래야 리액트가 <div>들을 각각 구분할 수 있어서 그렇습니다. 

없으면 워닝띄워줌 

 

 

 

 

 

 

 

(참고) 일반 for 반복문을 쓰고싶다면

 

1. html들을 담아둘 array 자료를 하나 만들어줍니다.

2. 일반 for 반복문을 이용해서 반복문을 돌림 

3. 반복될 때 마다 array자료에 <div> 하나씩 추가해줍니다. 

4. 원하는 곳에서 {array자료} 사용하면 됩니다. 

 

 

 

function App (){
  
  var 어레이 = [];
  for (var i = 0; i < 3; i++) {
    어레이.push(<div>안녕</div>)
  }
  return (
    <div>
      { 어레이 }
    </div>
  )
}

▲ 예를 들면 이런 식입니다.

이렇게 해도 <div>안녕</div> 이게 3개 출현합니다.

 

for 문법은 JSX 안에서 사용할 수 없어서 저렇게 바깥에서 쓰면 됩니다. 

귀찮으면 map을 씁시다. 

 

 

 

 

 

오늘의 숙제 :

지금 좋아요버튼을 누를 때 마다 모든 따봉갯수가 똑같이 1 증가하고 있습니다. 

각각 개별적으로 증가하게 하려면 어떻게 해야할까요?

 

(힌트) 지금 잘보면 따봉갯수를 기록할 state가 하나밖에 없어서 그렇습니다. 

그걸 모든 글제목들이 가져다 쓰고 있어서 그런 것일 뿐임 

 

직접 뭐라도 쳐봐야 실력이 늘기 때문입니다.

어려우면 반복문 쓰지 않은 이전강의 코드에서 시작해보십시오 더 쉽습니다. 

 

 

 

 

 

지금 따봉 기록할 state가 하나라서 그렇습니다.

let [따봉, 따봉변경] = useState(0);
let [따봉1, 따봉변경1] = useState(0);
let [따봉2, 따봉변경2] = useState(0);

이렇게 3개 만든 다음에 각각 글마다 집어넣어주면 완성입니다. 

근데 이렇게 만들면 글이 10개가 있을 경우 10줄 작성할 것입니까

그건 좀 귀찮기 때문에 array자료를 활용해도 됩니다.

 

 

let [따봉, 따봉변경] = useState([0,0,0]);

이렇게 array를 이용하면 한 변수에 자료 3개를 저장할 수 있으니까 이래도 됩니다. 

 

 

 

{ 
   글제목.map(function(a, i){
      return (
        <div className="list">
          <h4>{ 글제목[i] } 
            <span onClick={()=>{ ??? }}>👍</span> {따봉[i]} 
          </h4>
          <p>2월 18일 발행</p>
        </div> )
  }) 
}

▲ 그럼 따봉을 JSX안에 보여줄 때도 저렇게 보여주면 되겠군요. 일단 보여주는건 성공 

근데 onClick안에는 뭐 넣어야합니까? 

0번째 좋아요 버튼을 클릭시엔 따봉[0] + 1 을 해야하고

1번째 좋아요 버튼을 클릭시엔 따봉[1] + 1 을 해야하고

2번째 좋아요 버튼을 클릭시엔 따봉[2] + 1 을 해야하고

그러면 됩니다. 

근데 따봉이라는건 state니까 state 변경함수 써야합니다. 그리고 array자료니까 array 자료변경시 주의점도 신경써야겠군요. 

 

 

 

 

<h4> 
  { 글제목[i] } 
   <span onClick={()=>{ 
      let copy = [...따봉];
      copy[i] = copy[i] + 1;
      따봉변경(copy)  
   }}>👍</span> {따봉[i]} 
</h4> 

state가 array자료일 경우 복사부터 하고 

그거 수정하면 된다고 해서 그렇게 했습니다.

 

두번째 풀이는 그냥 copy 안 하고 하는 방법

 

Q. 저 코드 너무 어려워요 

원래 남의 코드 읽는건 세계최고로 어려운 일이라 직접 해보는게 더 이해빠름 

어려우면 map 반복문 쓰지 않은 이전 강의 코드에서 해보십시오 더 쉽습니다. 

 

array일 경우

자료 복사를 하자. copy=[...자료명] 

map 함수를 사용하자. 

 

 

관련글 더보기