리액트 json의 id 값에 따라 상세페이지로 이동하기 (useParams, Link)
Router.js
- 새 Route 를 만들어주고, path="" 와 element={} 를 넣어준다
- id 값에 따라서 다른 상세화면을 보여주고 싶으면, path=""상세페이지이름/:id" 를 넣어준다
더보기
//src > shared > Router.js
//Router.js
import React from 'react'
import {BrowserRouter, Routes, Route} from 'react-router-dom';
import Home from '../pages/Home';
import LetterDetails from '../pages/LetterDetails';
function Router() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}/>
{/* <Route path="letter-details" element={<LetterDetails />}/> */}
<Route path="letter-details/:id" element={<LetterDetails />}/>
</Routes>
</BrowserRouter>
)
}
export default Router
Home.jsx
- Home 컴포넌트가 반환하는 값에서 letter들이 보여지는 자식 컴포넌트 <List> 는 <Main> 컴포넌트의 자식 컴포넌트이다.
더보기
//src>pages>Home.jsx
//Home.jsx
// Hooks
import React from 'react';
import { useState } from 'react';
import moment from 'moment';
import { useEffect } from 'react';
import { useRef } from 'react';
import { useParams } from 'react-router-dom';
// CSS
import { styled } from 'styled-components';
import GlobalStyle from '../GlobalStyle';
// Components
import Header from '../components/Header';
import Footer from '../components/Footer';
import List from '../components/List';
import Button from '../components/Button';
// import Image from '../components/Image';
// Image
import picturePaul from '../assets/dune-Paul.png';
// Data Fetch
// import fakeData from "../database/fakeData.json";
const Main = styled.div`
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 60px;
`;
const ImgBtnBox = styled.div`
display: flex;
flex-direction: row;
gap: 60px;
`;
const PicturePaul = styled.img`
width: 430px;
`;
function Home() {
const [letterShown, setLetterShown] = useState({
'Paul' : true,
'Elio' : false,
'Gatsby' : false,
'Lee' : false,
});
const [createdAt, setCreatedAt] = useState("");
// fakeData 가져오기
// const [letters, setLetters] = useState(fakeData);
const [letters, setLetters] = useState([]);
useEffect(()=>{
const lettersData = require("../database/fakeData.json");
setLetters(lettersData);
},[])
const nowTime = moment().format('YYYY-MM-DD HH:mm:ss');
console.log(nowTime);
useEffect(()=> {
// GET CURRNET DATE & TIME
const now = moment();
// FORMATTING
const formattedTime = now.format('YY-MM-DD HH:mm:');
setCreatedAt(formattedTime);
},[])
const userNameRef = useRef('');
useEffect(()=> {
userNameRef.current.focus();
})
return (
<div>
<GlobalStyle />
<Header letters={letters} setLetters={setLetters} userNameRef={userNameRef}/>
<Main>
<ImgBtnBox>
<PicturePaul src={picturePaul} alt="Paul picture"/>
{/* <Image /> */}
<Button setLetterShown={setLetterShown} letters={letters}/>
</ImgBtnBox>
<List letters={letters.filter((letter)=>{
return letterShown[letter.wroteTo];
})}/>
</Main>
<Footer />
</div>
);
}
export default Home;
따라서 letter 를 눌렀을 때 상세페이지로 넘어가게 하려면 <List> 컴포넌트에서 useParams 와 Link 작업을 해줘야 한다.
List.jsx
- Link, useParams 를 import 하기
- letter 에 해당되는 태그 속성에 아래 코드 추가하기
to={`/letter-details/${letter.id}`
여기서 잠깐,
현재 Letter 로 컴포넌트화가 되어 styled-components로 꾸며져있는 태그를 Link 로 바꾸면 꾸미기 적용이 당연히 안된다.
이럴 땐, styled-components 를 꾸며주는 선언부에서 styled.div``; 에서 styled(Link)``; 로 바꿔주면 된다.
//BEFORE
const Letter = styled.div`
display: flex;
....
}
`;
//AFTER
const Letter = styled(Link)`
display: flex;
....
}
`;
전체코드
더보기
import React from 'react'
import {styled} from "styled-components";
import uuid from 'react-uuid';
import userIcon from '../assets/user-icon.png';
import { Link, useParams } from 'react-router-dom';
const ListArea = styled.div`
border: 1px solid black;
width: 450px;
height: 400px;
margin: 50px 25px 50px 25px;
overflow-y: scroll;
`;
const Letter = styled(Link)`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
color: black;
background-color: #e9e9e9;
margin: 20px;
padding: 10px;
gap: 5px;
height: 180px;
cursor: pointer;
text-decoration: none;
transition: 0.3s ease;
&:hover {
transform: scale(1.02);
background-color: #acacac;
}
`;
const Message = styled.span`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const UserIcon = styled.img`
align-self: start;
margin: 20px;
width: 50px;
`;
function List({letters, setLetters}) {
return (
<ListArea>
{letters.map((letter)=>{
return(
<Letter key={uuid()} to={`/letter-details/${letter.id}`}>
<UserIcon src={userIcon} alt="User Icon"/>
<div>
<h3>{letter.userName}</h3>
<p>{letter.createdAt}</p>
<span>To...{letter.wroteTo}, </span>
<Message>{letter.message}</Message>
<p>{uuid()}</p>
</div>
</Letter>
);
})}
</ListArea>
)
}
export default List
728x90
반응형