리액트

리액트>map : 많은 div들을 반복문으로 줄이고 싶을떄

연습노트 2024. 7. 12. 13:13

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

 

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

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

 

설명하다
 
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개나 생성됩니다.

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

 

대충 원리설명은

 

우선 [1, 2, 3] 에다가 map을 붙였으니 그 안의 자료 갯수만큼 map 내부 코드를 실행해줍니다.

근데 안에 return <div>안녕</div> 이게 있군요

그럼 <div>안녕</div> 이걸 array에 담아줍니다. 3번이나요

 

[ <div>안녕</div>, <div>안녕</div>, <div>안녕</div> ]

▲ 그럼 이게 남습니다.

 

근데 이걸 html로 미리보기 띄워볼 땐 

<div>안녕</div>
<div>안녕</div>
<div>안녕</div>

이렇게 보입니다. 

그래서 map을 써도 html 반복생성이 가능한 것임 

 

 

[collapse]

 

 

 

 

 

 

 

 

 

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

 

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

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

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

 

 

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

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

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

 

그래서 오늘의 결론은

비슷한 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라는 파라미터는 

map이 반복될 때마다 array자료 안에 있던 하나하나의 데이터들을 의미한다고 했습니다. 

그래서 a 출력해보면

반복문이 돌 때 마다 차례로 '남자 코트추천' '강남 우동 맛집' 이런 데이터들이 된다는 소리입니다.

그걸 그냥 <h4> 안에 집어넣었을 뿐입니다.

 

[collapse]

 

 

 

 

 

설명하다
 
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 이런 식으로 나옵니다. 진짜임  

 

 

 

 

 

 

 

 

 

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

 

 

설명하다
 
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자료일 경우 복사부터 하고 

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

 

 

 

Q. 저 코드 너무 어려워요 

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

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