본문 바로가기
  • 삽질하는 자의 블로그
React/React-TypeScript

2. React와 함께 TypeScript 사용하기(1), [ props 와 React.FC , 타입 아웃소싱, Type Aliases ]

by 이게뭐당가 2022. 12. 23.

1. 리액트와 함께 타입스크립트 사용하기

 

만들때 함께 설치한다.

	npx create-react-app my-app --template typescript

2. 만들고 나면

"자바스크립트는 tsx 로 변경"되어있고,

패키지에는
"@types/jest": "^27.5.2",
"@types/node": "^16.18.10",
"@types/react": "^18.0.26", 가 추가되어있다.

파일에는
"react-app-env.d.ts" 도 추가되어있다 

만든 "리액트 + 타입스크립트 앱"에서는,
"타입스크립트의 자바스크립트 컴파일이 자동"으로 이루어지고,
"tsx 코드를 사용해, JSX 코드 변환을 하여, 리액트에서 활용가능"하다.
"react-app-env.d.ts" 는 타입스크립트의 리액트와 연결고리 같은 것이다.

 

특수한 타입의 사용

 

1. props 를 받는 함수형 컴포넌트(Functional Component) 에서의 타입

 

    props 는 기본적으로 "객체" 이다.

    props.children, props.items, props.xxx,	...

    당연하게도 props 에서 오는 값의 타입을 "객체 타입" 의 지정으로 사용 할 수도 있다.

            cosnt Component = (props: { name: string, items: string[] }) =>{
                return ( ... )
            }	

            // 	props.name 은 string, 
            //	props.items 는, string 으로 이루어진 배열

	
    하지만, 리액트는 "함수형 컴포넌트" 를 위한, "특수한 타입"을 만들었다.
    
    바로 "React.FC" 타입이다. * 제네릭
    
        import React from "react";		// 필수는 아니다.

        const Todos: React.FC<{ items: string[]; amount: number }> = (props) => {    
            return (		 // Todos 함수형컴포넌트(FC) 에, React.FC 라는 타입을 정하고, props 객체의 타입을 정한다.
                <ul>
                    <li>{props.items}</li>      // 자동 완성이 나온다.
                    <li> {props.amount}</li>
                </ul>
            );
        };
        export default Todos;

 

2. props 를 사용하여, 값을 받고, 전개하기 [ 평소 만들던 Array]

<Component> ================================

        import React from "react";

        const Todos: React.FC<{ items: string[]; amount: number }> = (props) => {   
            return (
                <ul>
                    {props.items.map((item) => (    // items.map() 이 자동완성으로 나온다. [Array 인게 명확하기 때문에]
                        <li>{item}</li>
                    ))}
                </ul>
            );
        };
        export default Todos;


<App.js> ================================

        import Todos from "./components/Todos";

        function App() {
            return (
                <div className="App">
                    <Todos items={["sd", "gf"]} amount={3} />
                </div>
            );
        }

        export default App;



** 장점 : 
    타입이 확실히 정해지기 때문에, 자동완성으로 메서드들이 나온다
    "Array" 이면 ".map" 이라든가, ".filter" 라든가 하는것들

 

3.  그렇다면, 반복되는 타입을 일일이, 항상, 전부, 계속 반복하여 지정해야하나? 아니다! Type Aliases 의 사용

 

간단하게 타입이 두개 있는 함수형 컴포넌트를 정의해보자.

        import React from "react";

        const Todos: React.FC<{ items: {name:string, age:number}[]; amount: number }> = (props) => {
            return (
                <div>
                    <ul>
                        {props.items.map((item) => (
                        <li>{item.name}</li>
                        ))}
                    </ul>
                </div>
            );
        };
        export default Todos;


props 안에는 두개의 객체가 있다. 그것의 타입은 각각, 배열객체와, 숫자 이다.

    배열객체 items 안의 타입은      items: {name:string,age:number}[]
    숫자 amount 의 타입은 당연히    amount: number

 

 items 안에 담긴 프로퍼티가 name, age, address, phone, id, .... 등 수십가지라면?

저 items 를 받는 props 로 받는 컴포넌트함수 안에서는 얼마나 많은 정의를 해야할까?

그런 복잡성을 피하기 위해, "type 을 외부에서 정의하고, 사용해보자"

 

타입의 아웃소싱, "Type Aliases" 의 사용

< 이렇게 복잡하게 타입을 지정하지 말고 > ===================================

        import React from "react";

        const Todos: React.FC<{
            items: { name: string; age: number; address: string; phone: number }[];
            amount: number;
        }> = (props) => {
            return (
                <div>
                    <ul>
                        {props.items.map((item) => (
                            <li>{item.name}</li>
                        ))}
                    </ul>
                </div>
            );
        };
        export default Todos;


=========================================================================================================    

< models / todos.ts > ===================   // 컴포넌트함수 만들거 아니니까 그냥 ts 로 했다.

        export type Todo = {	// type 명령어를 사용한, Type alliases
            name: string;
            age: number;
            address: string;
            phone: number;
        };

< components/todos.tsx > ======================================

        import React from "react";
        import { Todo } from "../models/todos";		// 타입의 아웃소싱

        const Todos: React.FC<{ items: Todo[]; amount: number; }> = (props) => {	// 불러온 타입을 사용
            return (
                <div>
                    <ul>
                        {props.items.map((item) => (
                        <li>{item.name}</li>
                        ))}
                    </ul>
                </div>
            );
        };
        export default Todos;


=> 당연한 장점 : 
    1. 코드가 복잡해지지 않는다.
    2. 다른곳에서 같은 값의 props 를 쓸 때에도, 아웃소싱한 type 을 사용할 수 있다.
    3. 타입이 확실하니, 메서드도 자동완성이 되고, 값도 자동완성이 된다.

 

4. 단일 구성인 Item 컴포넌트, Item 컴포넌트의 상위 Items 컴포넌트로 All-Items 컴포넌트만들기 

 

평소에 하던 배열 만들기다. 다만 타입스크립트를 사용했을 뿐

props 를 사용하기 위해, React.FC<{}> 를 사용했을 뿐!

 

<App.js> ===================================================

        import Todos from "./components/Todos";

        const items = [
           { name: "ms", age: 3, address: "csd-x5", phone: 323 },
           { name: "cs", age: 5, address: "csd-x7", phone: 2323 },
        ];

        function App() {
            return (
                <div className="App">
                    <Todos items={items} amount={3} />
                </div>
            );
        }

        export default App;

<Todos.js> ===================================================

        import React from "react";      // 선택사항이다. 굳이 import 안해도 된다.
        import TodoItems from "./TodoItems";

        import { Todo } from "../models/todos";

        const Todos: React.FC<{     // props 로 받은 것은, 배열객체 타입의 items 와, 숫자 타입의 amount
            items: Todo[];          // items 의 "타입지정"은 "modles/todos.ts" 에서 "아웃소싱" 타입 별칭(Type aliases) 에일리어스
            amount: number;
        }> = (props) => {

            return (        
                <div>
                    <ul>
                        {props.items.map((item) => (        // 평소처럼, Item(단일항목) 컴포넌트를 만들어서, 배열을 만들기
                            <TodoItems key={item.phone} todoName={item.name} />
                        ))}
                    </ul>
                </div>
            );
        };

        export default Todos;

<TodoItems.js> ===================================================

        import React from "react";

        const TodoItems: React.FC<{ todoName: string }> = (props) => {  // props 로 받은 것은, string 타입의 todoName 뿐!
            return <div>{props.todoName}</div>;
        };

        export default TodoItems;

댓글