[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 3
2024. 8. 25. 12:18
사전직무교육 Day3
오늘은 프로젝트 캠프에서의 셋째날이다.
이 날 병원 진료때문에 온라인 수업을 들었고, 기업 프로젝트 팀 미팅시간에는 참여하지 못해 내 이름이 없다..😭
오늘은 지난 시간에 이어 컴포넌트 스타일링 라이브러리와 폰트 적용 방법에 대해 배우고,
본격적으로 리액트 컴포넌트 문법과 이벤트, props를 배웠다!!
드디어 제일 기다리고 기다리던 시간.. (두근두근)
🧚♂️ Tailwind CSS
- Tailwind CSS 공식문서에 나온 프레임워크 별 가이드라인대로 설치 진행 후 기본 세팅
- tailwind-merge
- 클래스가 중복될 경우 병합하기 위해 사용하는 라이브러리
- twMerge()
- 병합의 우선순위는 뒤에 있는 속성
- 클래스 중복을 제거
- twJoin()
- 병합의 우선순위 상관 없이 병합
- 클래스를 합쳐줌
- twMerge()
- 클래스가 중복될 경우 병합하기 위해 사용하는 라이브러리
- tailwind-forms
- tailwind의 기본 폼 스타일을 구성
- tailwind를 index.css 파일에 초기화하게 되면, 모든 스타일이 초기화되므로 기본 폼 스타일링을 해주는 패키지
- tailwind.config.js 파일에 플러그인을 적용해야함
💄 CSS-in-JS
- Styled-Components
- 가장 대중적인 CSS-in-JS 라이브러리
- Emotion
- Styled-Components의 단점을 개선하여 나옴
- Vanilla Extract
- 런타임 과정에서 연산 작업을 하지 않도록 빌드 과정에서 연산 작업을 끝냄 (Zero run time)
- 성능 개선을 위해 등장
- 안정성은 아직 떨어지기 때문에 별도의 추가 세팅이 필요함
- Linaria
- Zero run time
✅ React 컴포넌트
컴포넌트 트리 구조
- DOM 트리에는 형제 노드가 존재하지만, 리액트 컴포넌트 트리에는 오직 부모와 자식뿐임
- 리액트는 깊이 우선 탐색(Depth-First Search, DFS) 알고리즘을 사용하여 컴포넌트를 생성하고 렌더링 함
- 특정 컴포넌트가 업데이트 되면 해당 컴포넌트는 리렌더링 됨
- 하지만 만약 해당 컴포넌트에 하위 컴포넌트가 존재한다면 같이 리렌더링 됨
- 반대로, 하위 컴포넌트에 업데이트가 있을 경우엔 상위 컴포넌트에 영향을 주지 않음
- 그래서 렌더링 최적화를 위해 리렌더링이 불가피한 컴포넌트가 최하위가 될 수 있도록 컴포넌트를 설계하는 것이 중요함!
컴포넌트 이벤트
- 이벤트 타입은 타입추론을 통해 확인이 가능함
- 폼 이벤트
- onChange
- onSubmit
- 마우스 이벤트
- onClick
- onMouseEnter
- onMouseLeave
- 키보드 이벤트
- onKeyDown
- onKeyPress
- onKeyUp
- 포커스 이벤트
- onFocus
- onBlur
- 드래그 이벤트
- onDragStart
- onDragOver
- onDrop
- 터치 이벤트
- onTouchStart
- onTouchMove
- onTouchEnd
- 함수 자체를 이벤트로 전달할 경우 이벤트 객체(event)가 자동으로 넘어가서 바로 활용이 가능함
<button onClick={onClickHandler}>버튼 클릭</button>
- 콜백 함수로 함수를 이벤트로 전달할 경우 명시적으로 이벤트 객체(event)를 매개변수로 넘겨줘야 활용 가능
<button onClick={(e)=>onClickHandler(e)}>버튼 클릭</button>
컴포넌트 Props
- 컴포넌트 간에 데이터를 전달하는 방법
- 부모 컴포넌트에서 자식 컴포넌트에 전달하는 읽기 전용 데이터임
- props를 활용함으로써 컴포넌트의 재사용성이 높아짐
- 기본 사용법
// Greeting.jsx
const Greeting = (props) => {
return <h1>Hello, {props.name}</h1>
}
// Greeting.tsx
const Greeting = (props: { name: string }) => {
return <h1>Hello, {props.name}</h1>
}
//App.jsx
const App = () => {
return (
<>
<Greeting name="Mia" />
<Greeting name="승미" />
<Greeting name="뜽" />
</>
)
}
- 표현식 사용법
const App = () => {
return (
<>
<Greeting name={"Mia"} />
<Greeting name={"승미"} />
<Greeting name={"뜽"} />
</>
)
}
- 구조분해할당
// Greeting.tsx
const Greeting = ({ name }: { name: string }) => {
return <h1>Hello, {name}</h1>
}
- 여러 개의 Props 전달
// UserCard.tsx
// 구조분해할당 + 여러개 props 전달
const UserCard = ({ name, age, gender }: {name: string; age: number; gender: string;}) => {
return (
<>
<p>{name}</p>
<p>{age}</p>
<p>{gender}</p>
</>
)
}
// App.tsx
// 기본 사용 + 표현식 사용
const App = () => {
return (
<>
<UserCard name="Mia" age={30} gender={"female"}/>
<UserCard name="Kai" age={20} gender={"male"}/>
<UserCard name="승미" age={10} gender={"female"}/>
</>
)
}
- props로 이벤트나 함수를 전달할 수 있음
// UserCard.tsx
const UserCard = ({ name, age, gender, onClickHandler }: {name: string; age: number; gender: string; onClickHandler: (name: string, age: number, gender: string) => void;}) => {
return (
<>
<p>{name}</p>
<p>{age}</p>
<p>{gender}</p>
<button onClick={()=>onClickHandler(name, age, gender)}>버튼 클릭</button>
</>
)
}
// App.tsx
const App = () => {
const onClickHandler = (name: string, age: number, gender: string) => {
alert(`${name}, ${age}, ${gender === "male" ? "남자" : "여자"}`)
}
return (
<>
<UserCard name="Mia" age={30} gender={"female"} onClickHandler={onClickHandler}/>
<UserCard name="Kai" age={20} gender={"male"} onClickHandler={onClickHandler}/>
<UserCard name="승미" age={10} gender={"female"} onClickHandler={onClickHandler}/>
</>
)
}
- 타입스크립트의 경우 모든 props의 타입을 지정해주어야 함
- interface, type 등으로 모듈화 후 사용
- 직접 props 매개변수에 타입지정 후 사용
📚 오늘의 과제
- 프로필 카드 컴포넌트 만들기
- ProfileCard 컴포넌트 생성
- 배경 이미지, 유저 이미지, 유저 이름, 인스타 아이디를 props로 전달
- [Follow] 버튼을 클릭했을 때 클릭 이벤트가 발생할 수 있도록 이벤트를 props로 전달
// ProfileCard.tsx
interface ProfileCardProps {
cardImg: string;
userImg: string;
userName: string;
ig: string;
onClickHandler: () => void;
}
const ProfileCard = ({ ...props }: ProfileCardProps) => {
return (
<article className="card">
<div>
<img className="card-img" src={props.cardImg} alt="background-pic" />
</div>
<div className="profile">
<img className="prof-img" src={props.userImg} alt="profile-pic" />
<h3 className="alias">{props.userName}</h3>
<p className="username">{props.ig}</p>
<button onClick={props.onClickHandler}>Follow</button>
</div>
</article>
);
};
export default ProfileCard;
// App.tsx
import ProfileCard from './components/ProfileCard';
function App() {
const imgSrc: string[] = [
'https://cdn.pixabay.com/photo/2021/01/08/06/32/cafe-5899078_1280.jpg',
'https://cdn.pixabay.com/photo/2019/10/03/13/20/cat-4523300_1280.jpg',
];
const onClickHandler = () => {
alert('You have successfully followed!');
};
return (
<ProfileCard
cardImg={imgSrc[0]}
userImg={imgSrc[1]}
userName="Meow"
ig="@meow"
onClickHandler={onClickHandler}
/>
);
}
export default App;
가독성을 위해 props 들의 타입을 interface로 정의 후 ProfileCard 컴포넌트를 생성했다.
상위 컴포넌트인 App 컴포넌트에서 cardImg, userImg, userName, ig를 props로 전달했고,
[Follow] 버튼을 클릭했을 때 발생하는 이벤트 핸들러 함수 onClickHandler를 선언하여 props로 전달했다.
본격적으로 리액트 컴포넌트에 대해 배우면서 앞으로 배우게 될 내용이 중요하기 때문에 수업에 더 집중하고, 빠지지 않아야 흐름을 놓치지 않겠다는 생각을 했다.
이번 과제를 통해 props에 대해 좀 더 고민해보는 시간을 가질 수 있었고, 어떻게 해야 계속 늘어나는 props를 가독성 좋게 리팩토링 할 수 있을지도 고민할 수 있는 시간을 가질 수 있었다.
빠지지 말고 내일도 힘내보자!!!! 😎
본 후기는 본 후기는 [유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 과정(B-log) 리뷰로 작성 되었습니다.
'Myalog > Study' 카테고리의 다른 글
[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 6 (1) | 2024.09.02 |
---|---|
[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 5 (0) | 2024.08.25 |
[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 4 (0) | 2024.08.25 |
[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 2 (0) | 2024.08.20 |
[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 1 (4) | 2024.08.19 |