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);
 
 
const handleClick = (i: number) => {
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);
};
}, []);

반응형