React/과제 테스트
[인사정보] React url 절대 경로, url 전환, 카드 뒤집기, 로컬스토리지, 스크롤 동작
Judith Hopps
2023. 8. 9. 19:29
반응형
과제 테스트 준비
애니메이션과 로컬스토리지, 무한 스크롤 기능을 작성해봤다.
🐇 url 절대경로
모든 경로 앞에 /web/을 절대경로로 붙여주어야 합니다
1. import Router
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
2. App.tsx 파일 수정
<div>
<Router basename={baseUrl}>
<Header /> // 모든 페이지에 보임
<Routes>
<Route path="/" element={<Home userData={userData} />} />
<Route path="/signup" element={<SignUp />} />
<Route path="*" element={<NotFounnd />} />
</Routes>
</Router>
</div>
🐇 url 전환
header의 menu를 누르면 url 바뀌어야 한다.
1. header 작성
2. react-router-dom 설치
3. Link to로 전환
// import styles from "./style/app.module.css"
import styles from "../style/app.module.css";
import { Link } from "react-router-dom";
type RouteType = "Home" | "Signup";
const Header = () => {
return (
<header className={styles.header}>
<Link to="/">
<button className={styles.headerButton}>HOME</button>
</Link>
<Link to="/signup">
<button className={styles.headerButton}>SIGNUP</button>
</Link>
</header>
);
};
export default Header;
※ useHistory
또는 useHistory 사용하는 방법도 있다.
const history = useHistory();
<button onClick={() => history.push('/new-page')}>새 페이지로 이동</button>
🐇 카드 뒤집기
유저가 카드를 클릭하면 카드가 뒤집어 지고 다른 설명이 보여야 한다.
0. 먼저 카드와 컨테이너의 css를 작성해준다.
/* 카드 */
.card {
margin: 20px 10px;
width: 100px;
height: 100px;
border-radius: 25px;
transform-style: preserve-3d;
transform-origin: center right;
transition: transform 1s;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
background-color: #0d0d0d;
color: white;
display: flex;
justify-content: center;
align-items: center;
}}
// 카드 컨테이너
<div
style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "center",
alignContent: "center",
}}
>
1. 카드가 뒤집히는 효과를 주는 animation을 작성해준다.
🥕 애니메이션 효과
※ keyframes
@keyframes rotateBack {
0% (from){
transform: translateX(-100%) rotateY(-180deg);
}
100%(to) {
transform: translateX(0) rotateY(0deg);
}
}
.card.is-flipped {
animation: rotateBack 1s ease forwards; /* 1초 동안 rotateBack 애니메이션 실행 */
}
ex)
@keyframes lotate {
0% {
transform : rotate(0deg)
}
50% {
transform : rotate(180deg)
}
100% {
transform : rotate(360deg)
}
}
2. 카드를 클릭하면 className을 바꿔주고 state로 관리한다.
const handleClick = (i: number) => {
setFlipped("is-flipped");
setTimeout(() => {
setFlipped(""); // 1초 후에 뒤집힘 상태 초기화
}, 1000);
};
3. card에 className 입력한다.
<section
key={i}
className={`${styles.card} ${
current === i ? styles[flipped] : ""
} `}
onClick={() => handleClick(i)}
style={{ cursor: "pointer" }}
// style={{
// width: 200,
// marginRight: 20,
// height: 260,
// backgroundColor: "#0D0D0D",
// color: "white",
// borderRadius: "10%",
// // textAlign: "center",
// // 카드 정가운데 위치
// display: "flex",
// justifyContent: "center",
// alignItems: "center",
// fontSize: 40,
// fontWeight: 700,
// }}
>
🥕 카드 정가운데에 아이템이 위치해야 한다.
display: flex;
justify-content: center;
align-items: center;
4. 사용자가 클릭한 카드만 애니메이션이 동작하도록 id 조건을 확인한다.
const [flipped, setFlipped] = useState("");
const [current, setCurrent] = useState(-1);
setCurrent(i);
};
<section
key={i}
className={`${styles.card} ${
current === i ? styles[flipped] : ""
} `} >
🐇 로컬 스토리지 저장
1. 데이터는 로컬스토리지가 처음 생성될 때 로컬스토리지에 저장됩니다.
2. 브라우저 창 종료 후 재접속 했을 때, 카드의 뒤집힌 상태가 유지되도록 카드의 상태를 로컬스토리지에 기록합니다.
0. http util 함수 생성한다.
import Axios from "axios";
const axios = Axios.create();
export const http = {
get: function get<Response = unknown>(url: string) {
return axios.get<Response>(url).then((res) => res.data);
},
post: function post<Response = unknown, Request = any>(
url: string,
body?: Request
) {
return axios.post<Response>(url, body).then((res) => res.data);
},
};
1. 먼저 데이터를 가져온다.
useEffect(() => {
const fetchUserData = async () => {
// 로컬스토리지에 데이터 있는지 확인
if (localStorage.getItem("personalInfo") !== null) return;
// 로컬스토리지에 데이터 없으면 저장
const personalInfo = await http.get(
);
console.log(personalInfo);
localStorage.setItem("personalInfo", JSON.stringify(personalInfo));
};
fetchUserData();
}, []);
2. localstorage 저장
localstorage 저장 -> stringfy
localstorage 추출 -> parse
useEffect(() => {
const setData = () => {
const data = localStorage.getItem("personalInfo");
if (data) setUserData(JSON.parse(data));
};
setData();
}, []);
※ JSON
JSON이란?
JavaScript Object Notation을 의미하며 경량화한 텍스트기반 데이터 교환 방식을 의미한다.
즉, 문자 기반의 데이터 포맷이다.
JSON.parse()
전달받은 문자열을 자바스크립트 객체로 변환한다.
console.log(JSON.parse('{"name":"iu", "age":30}'));
// 출력 결과
{name: "iu", age: 30}
JSON.stringify()
자바스크립트 객체를 문자열로 변환한다.
매겨변수로 value, replacer, space를 받을 수 있다.
replacer와 space는 선택사항이고 value는 JSON 문자열로 반환하고 싶은 값을 넣어주면 된다.
const test = {
name : '아이유',
age : 30
}
console.log(JSON.stringify(test));
// 실행 결과
{"name":"아이유","age":30}
🥕 props로 api 데이터 전송시
※ 부모
import React from "react";
import Card from "../component/Card";
import { UserDataType } from "../type/type";
type HomeProps = {
userData?: UserDataType[];
};
const Home: React.FC<HomeProps> = ({ userData }) => {
return (
<div>
<Card userData={userData} />
</div>
);
};
export default Home;
※ 자식
type CardProps = {
userData?: UserDataType[];
};
type CardStatusType = {
id: number;
status: string;
};
const Card: React.FC<CardProps> = ({ userData }) => {} )
🐇 무한 스크롤
페이지 하단에 도달했을 때, 그다음 카드가 순차적으로 계속 로드되는 사용자 경험을 제공하기 위해 무한스크롤 기능을 구현합니다.
동작할 함수 생성 및 이벤트 등록
// 무한 스크롤 동작
const handleScroll = () => {
const windowHeight = window.innerHeight;
const scrollY = window.scrollY || window.pageYOffset;
const bodyHeight = document.body.scrollHeight;
if (scrollY + windowHeight >= bodyHeight) {
// 페이지 하단에 도달했을 때 새로운 카드 로드
setVisibleCards((prevVisibleCards) => prevVisibleCards + 4);
}
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
반응형