폴더명 todo-list
사전코드 : react typescript 기본 테스트 코드 :: Web Backend Developer (tistory.com)
버튼 컴포넌트 1개 생성
App.tsx
import React from 'react';
import Styled from 'styled-components';
const Container = Styled.div`
min-height: 100vh;
background-color: #EEEEEE;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
`;
const Contents = Styled.div`
display: flex;
background-color: #FFFFFF;
flex-direction: column;
padding: 20px;
border-radius: 8px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
`;
const Button = Styled.div`
text-align : center;
background-color : #304FFE;
padding : 10px 20px;
border-radius : 8px;
cursor : pointer;
&:hover {
background-color : #1E40FF;
}
&:active {
box-shadow : inset 5px 5px 10px rgba(0,0,0,0.2);
}
`;
const Label = Styled.div`
color : #FFFFFF;
font-size : 16px;
`;
function App() {
return (
<Container>
<Contents>
<Button>
<Label>추가</Label>
</Button>
</Contents>
</Container>
);
}
export default App;
실행결과
버튼 컴포넌트를 재사용
src/Components 폴더를 생성
src/Components/Button 폴더를 생성
src/Components/index.tsx 파일 생성
import React from "react";
import Styled from "styled-components";
const Container = Styled.div`
text-align : center;
background-color : #304FFE;
padding : 10px 20px;
border-radius : 8px;
cursor : pointer;
&:hover {
background-color : #1E40FF;
}
&:active {
box-shadow : inset 5px 5px 10px rgba(0,0,0,0.2);
}
`;
const Label = Styled.div`
color : #FFFFFF;
font-size : 16px;
`;
export const Button = () => {
return (
<Container>
<Label>추가</Label>
</Container>
);
}
export const Button = () => {
...
}
// export default 인 경우
import Button from 'Components/Button'
// export 인경우
import { Button } from 'Components/Button'
// export 장점
import { Button, Text, Icon } from 'Components'
src/Components/index.tsx 파일 생성
* 여러 컴포넌트를 한곳에 관리하기 위해 처리
export * from './Button';
App.tsx 에 Button 컴포넌트 적용
import React from 'react';
import Styled from 'styled-components';
import {Button} from "Components";
const Container = Styled.div`
min-height: 100vh;
background-color: #EEEEEE;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
`;
const Contents = Styled.div`
display: flex;
background-color: #FFFFFF;
flex-direction: column;
padding: 20px;
border-radius: 8px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
`;
function App() {
return (
<Container>
<Contents>
<Button/>
</Contents>
</Container>
);
}
export default App;
Props 활용
Props는 부모 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터이다.
현재 부모 컴포넌트는 App 컴포넌트가 되며, 자식 컴포넌트는 Button 컴포넌트가 된다.
Button/index.tsx
interface Props {
readonly label : String;
}
export const Button = ({label} : Props) => {
return (
<Container>
<Label>{label}</Label>
</Container>
);
}
/*
전달받는 데이터가 많아지고 전달받은 데이터를 자식 컴포넌트에서 자주사용 하면
매번 객체에 접근하여 값을 사용하는 것은 매우 비효율적이다.
따라서 실무에서는 다음과 같이 자바스크립트의 구조 분해 할당(Destructuring assignment) 문법을
사용하여 전달받은 데이터를 분해 할당해서 사용한다
*/
* 전달받은 label 데이터의 데이터 타입을 체크하기 위해 타입스크립트의 인터페이스를 사용하여 Props 라는 이름의 인터페이스를 정의하였고 해당 인터페이스에 문자열 데이터와 읽기 전용으로 정의하였다.
// 기본포맷
export const Button = ("부모 컴포넌트로부터 전달받는 데이터") => { .... }
export const Button = (props) => { ... }
/*
프로그램을 실행하기 전까지 이렇게 전달받는 데이터가 어떤 데이터 타입를
포함하는지 알수없다. 그러므로 부모 컴포넌트로부터 해당값을 전달받지 않았다면
실행 중에 에러가 발생한다.
*/
export const Button = (props : Props) => {
return (
<Container>
<Label>{props.label}</Label>
</Container>
);
}
/*
부모 컴포넌트로부터 전달받는 모든 데이터는 우리가 정의한 props라는 매개변수에
객체 형태로 전달받게 된다. 따라서 위와 같이 사용하고자 하는 곳에서는
props.label 과 같이 객체의 속성값에 접근하는 형태로 사용할 수 있다.
*/
App.tsx
<Button label="추가1"/>
<br/>
<Button label="추가2"/>
부모 컴포넌트에서 Props를 통해 Button 컴포넌트의 배경 색상을 설정할 수 있다.
interface Props {
readonly label : String;
readonly backgroundColor?: string;
readonly hoverColor?: string;
}
// ? 은 옵션이라는 뜻
/*
label : 필수값
backgroundColor : 옵션값
hoverColor : 옵션값
*/
export const Button = ({
label,
backgroundColor = '#304FFE',
hoverColor = '#1E40FF'
} : Props) => {
return (
<Container backgroundColor={backgroundColor} hoverColor={hoverColor}>
<Label>{label}</Label>
</Container>
);
}
이제 npm start 하면 에러가 발생한다.
TS2769: No overload matches this call.
오류 해결방법 : [TypeScript] React에서 TypeScript 적용하기 & 오류 해결하기 (velog.io)
TS + styled-components를 사용하면서 발생한 문제
정확히 말하면 스타일드 컴포넌트에서 내가 임의로 만든 props를 전달하려고 하니까 발생한 문제
* 자세한 내용은 해당 사이트 참고
해결방법
interface ContainerProps {
readonly backgroundColor: string;
readonly hoverColor: string;
}
const Container = Styled.div<ContainerProps>` // 제네릭 문법 사용
text-align : center;
background-color : ${(props) => props.backgroundColor};
padding : 10px 20px;
border-radius : 8px;
cursor : pointer;
&:hover {
background-color : ${(props) => props.backgroundColor};
}
&:active {
box-shadow : inset 5px 5px 10px rgba(0,0,0,0.2);
}
`;
* 제네릭란?
제네릭 | 타입스크립트 핸드북 (joshua1988.github.io)
제네릭은 C#, Java 등의 언어에서 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징입니다. 특히, 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를 생성하는데 사용됩니다.
이제 App.tsx 수정
function App() {
return (
<Container>
<Contents>
<Button label="추가"/>
<br/>
<Button label="삭제" backgroundColor="#FF1744" hoverColor="#F01440"/>
</Contents>
</Container>
);
}
결과
'2022 > 리액트+TDD(完)' 카테고리의 다른 글
Props / State - 3 (0) | 2022.01.08 |
---|---|
Props / State - 2 (0) | 2022.01.05 |
react typescript 기본 테스트 코드 (0) | 2022.01.05 |
TypeScript 적용3 - 절대경로 / Prettier 소개 (0) | 2022.01.04 |
TypeScript 적용2 - style-components (0) | 2022.01.04 |