(21.08.02) Typescript에서 React Props를 받기 / React에서 배열 랜더링

도깨비젤리

·

2021. 8. 2. 22:38

작은 지식이라도, 하루에 하나씩.


 

한 줄 요약


🦄하위 컴포넌트로 Props를 내려 줄 때, Props를 받는 곳에서 타입을 지정해줘야 한다.🦄
🦄React에서 배열을 랜더링 하려면 map 함수를 사용한다는 것, 잊지 말자.🦄

 

 

하위 컴포넌트로 Props를 줘보자.


// interface.ts
//프로필에 띄울 개별 Article들의 type입니다.
export interface ArticleProps {
  title: string;
  description: string;
  imagePaths: any;
  ingredients: string;
  createDate: string;
}

자주 사용될 타입을 먼저 작성하여 export 하여, 타입을 여러번 타이핑 하는 수고를 덜기 위해 작성했다.

 

인터페이스를 export 시켜서 사용하는 건 매우 편리하다. 복잡한 타입을 가지고 있는 자료들도 import 한 방에 해결할 수 있으니, 이러한 방식에 익숙해지도록 하자.

 

 

//ArticleContainer.tsx
//Article 컴포넌트를 묶어주고 있는 상위 컴포넌트이다.


<div className="container">
    {props.fetchedMypagePostDtos.map((article: any) => {
      return (
        <Articles
          key={uuidv4()}
          title={article.title}
          description={article.description}
          imagePaths={article.imagePaths}
          ingredients={article.ingredients}
          createDate={article.create_date}
       />
     );
   })}
</div>

그럼, 위와 같은 타입을 작성하여 export한 이상, 우리는 Articles라는 컴포넌트에 title,description,imagePaths,ingredients,createDate라는 속성이 있음을 알고 있다. 그러나, 아무런 액션 없이 바로 위와 같이 props를 지정해주면 또 다시 vscode가 에러를 마구마구 뿜어낸다.

 

이유인 즉슨, "니가 Articles에 뭘 내려보내려는 건 알겠는데, Articles 이 친구는 그런 props 받을 예정이 없다는데??" 라는 것이다.

 

그렇기 때문에 우리는 미리 하위 컴포넌트인 Articles로 내려가서 type을 지정해주어, 어떤 친구들이 내려올것이라는 걸 알려줘야한다.

 

 

ps) 지금 article : any로 되어있는데, 얘한테는 ArticleProps 타입이 안 들어가서 부득이하게 any를 넣었습니다.왜 ArticleProps 타입이 안들어가는지 감 잡히시는 분 있으면 댓글로 꼭 좀 알려주셨으면 합니다 👩‍💻👩‍💻

 

 

//Articles.tsx
// parameter에 props라는 임시 변수를 넣어서, 내려받은 속성들을 props. 으로 접근 가능하게 함
// interface로 <ArticleProps>를 설정해준것.

const Articles: React.FC<ArticleProps> = (props) => { 

 ... 중략
 
  return (
    <Card className="card--wrapper">
      <CardActionArea>
          <Typography gutterBottom variant="h5" component="h2">
            {props.title} // 요롷게 위에서 받은 title에 접근 가능
          </Typography>

... 후략

 

Articles 컴포넌트에 ArticleProps 인터페이스를 불러와서 장착하니 에러 없이 깔끔하게 되는 모습입니다.

 

 

React에서 컴포넌트 반복


코딩하다보면 axios등으로 서버에서 데이터를 받아온 다음, 받아온 데이터를 토대로 컴포넌트를 만들어야 하는 경우가 많습니다. 그 중에서도 [ { } , { } , { } ...] 꼴의 Object in Array 꼴의 데이터를 많이 접하게 되는데, 각 원소에 접근해서 데이터를 뽑아야합니다. 이때 map 함수를 사용해서 배열을 쉽게 랜더링 할 수 있습니다.

 

 

let [heroines, setHeroine] = useState( ['power-ko','klee','makima-san','zero-two'] );

const App:React.FC = () => {
  return (
    <div>
      중략
      ...
      { 
      heroines.map(function(heroine){
      // 주의! return 빼먹지 마라!!
        return (
        <div className="list" key = {uuid4()}>
          <h3>{ heroine }</h3>
          <p>2월 18일 발행</p>
          <hr />
        </div>
      }) 
      }
    </div>
  )
}

주석에도 작성해두었지만, return을 빼먹지 마라. 만약 JS syntex는 return이 한줄로 끝난다면 return을 생략하는 것을 허락하지만 ( 사실 이거 좀 웃기다고 생각한다 ), 나 같은 경우는 return을 빼먹게 되면 함수가 어떤 컴포넌트를 만들게 되는지에 대한 시야가 열리질 않는다.

 

즉, 가독성이 떨어지기 때문에 나는 항상 map 함수를 쓸 때 return문을 적어준다.  근데 이건 제 개인적인 기벽이므로 판단은 여러분들이 알아서 하시길 바랍니다.

 

 

또한, map 함수로 컴포넌트를 반복 생성 할 때는 반드시 wrapper level의 태그에 key 값을 부여해줘야합니다.

이건 react, vue 등 모던 프레임워크에 공통적으로 적용되는 내용인데, key 값을 부여하지 않으면 배열에 어떤 요소를 추가되거나 바뀔 때 어떤 값이 추가되었고 변경되는지 캐치하지 못합니다. 그렇기 때문에 고유한 key 값을 부여하는것이 매우 중요합니다.

 

이 고유한 키 값을 부여하기 위해 보통 uuid라는 라이브러리를 사용합니다.

 

https://www.npmjs.com/package/uuid

 

uuid

RFC4122 (v1, v4, and v5) UUIDs

www.npmjs.com

 

uuid는 호출할때마다 고유한 id를 반환해줍니다. 엄청 복잡한 로직으로 돌아가기 때문에 중복이 발생할 염려가 없기에 안심하고 사용하시면 되겠습니다.

 

간혹 index 값을 key로 사용하는 분들도 계시는데, 배열의 변동에 따라서 key 값이 복잡하게 꼬일 수 가 있습니다. 그렇게 되면 react가 어떤 요소가 바뀌었는지 명확하게 파악하지 못해 예상외의 동작을 할 수 가 있습니다.

 

애초에, index를 key로 주면 개발자 도구에서 경고를 무진장 띄웁니다.

 

그냥 uuid 사용하시길 바랍니다