[REACT] 10_상세페이지 작성 1
2021. 12. 27. 13:10ㆍReact/React 쇼핑 앱
반응형
상품 상세페이지(Detail.js)에 부트스트랩 TABS 컴포넌트 삽입
https://react-bootstrap.netlify.app/components/navs/#tabs
<Nav variant="tabs" defaultActiveKey="/home">
<Nav.Item>
<Nav.Link href="/home">Active</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link-1">Option 2</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="disabled" disabled>
Disabled
</Nav.Link>
</Nav.Item>
</Nav>
CSSTranstition 라이브러리 추가
yarn add react-transition-group
http://reactcommunity.org/react-transition-group/css-transition
Detail.js
더보기
import { useParams, useHistory } from "react-router-dom";
import { Nav } from 'react-bootstrap';
import { useEffect, useState } from "react";
import { CSSTransition } from "react-transition-group";
import './Detail.css';
function Detail(props) {
let { id } = useParams();
let foundObj = props.shoes.find((obj) => {
return obj.id == id;
});
console.log(foundObj);
let history = useHistory();
let [tabIdx, setTabIdx] = useState(0);
let [transSw, setTransSw] = useState(false);
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={foundObj.image} alt="이미지" width="100%" />
</div>
<div className="col-md-6 mt-4">
<h4 className="pt-5">{foundObj.title}</h4>
<p>{foundObj.name}</p>
<p>{foundObj.content}</p>
<p>{foundObj.price}</p>
<a class="btn btn-primary" role="button">장바구니</a>
<a class="btn btn-secondary" role="button" onClick={() => {
history.goBack();
}}>뒤로가기</a>
</div>
{/* tab menu */}
<Nav variant="tabs" defaultActiveKey="link-0">
<Nav.Item>
<Nav.Link eventKey="link-0" onClick={() => {
setTransSw(false);
setTabIdx(0);
}}>TAB 1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link-1" onClick={() => {
setTransSw(false);
setTabIdx(1);
}}>TAB 2</Nav.Link>
</Nav.Item>
</Nav>
{/* tab content */}
<CSSTransition in={transSw} classNames="trans" timeout={200}>
<TabContent tabIdx={tabIdx} setTransSw={setTransSw} />
</CSSTransition>
</div>
</div>
)
}
function TabContent(props) {
useEffect(() => {
props.setTransSw(true);
});
return (
<>
<div>{props.tabIdx} 번째 탭 선택됨</div>
</>
)
}
export default Detail;
Detail.css
더보기
.trans-enter {
opacity: 0;
}
.trans-enter-active {
opacity: 1;
transition: opacity 200ms;
}
App.js
Detail 태그에 shoes 라는 속성값도 전달한다.
더보기
import React from 'react';
import { Container, Navbar, Nav, NavDropdown } from 'react-bootstrap';
import './App.css';
import Shoes1 from './api/shoes1.json';
import { useState } from 'react';
import axios from 'axios';
import { Route, Switch } from 'react-router-dom';
import Detail from './Detail';
import { useHistory } from 'react-router-dom/cjs/react-router-dom.min';
function App() {
let [shoes, setShoes] = useState(Shoes1);
let [pageIdx, setPageIdx] = useState(2);
return (
<div className="App">
{/* navbar */}
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
<Container>
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="/">Home</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<NavDropdown title="Dropdown" id="collasible-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
<Nav>
<Nav.Link href="#login">로그인</Nav.Link>
<Nav.Link eventKey={2} href="#join">
회원가입
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
{/* jumbotron */}
<Switch>
<Route exact path='/'>
<div class="bg-light p-5 rounded-lg m-3">
<h1 class="display-4">Hello, world!</h1>
<p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>
<hr class="my-4" />
<p>It uses utility classes for typography and spacing to space content out within the larger container.</p>
<a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</div>
{/* card components */}
<div className='container'>
<div className='row'>
{
shoes.map((obj, i) => {
return <Card key={i} i={i} shoes={shoes} />
})
}
</div>
</div>
{/* 더보기 */}
<a class="btn btn-secondary btn" role="button" onClick={() => {
axios.get('https://ksky216.github.io/json/data' + pageIdx + '.json').then((resp) => {
setShoes([
...shoes,
...resp.data
]);
setPageIdx(pageIdx + 1);
}).catch((e) => {
console.log(e);
});
}}>더보기</a>
</Route>
<Route exact path="/detail/:id">
<Detail shoes={shoes} />
</Route>
</Switch>
</div>
);
}
function Card(props) {
let history = useHistory();
return (
<>
<div className='col-md-4' onClick={() => {
history.push("/detail/" + props.shoes[props.i].id);
}}>
<img src={ props.shoes[props.i].image } alt="신발" width="100%" />
<h3>{ props.shoes[props.i].title }</h3>
<p>{ props.shoes[props.i].content } & { props.shoes[props.i].price }</p>
</div>
</>
)
}
export default App;
반응형
'React > React 쇼핑 앱' 카테고리의 다른 글
[REACT] 12_장바구니(카트) 작성 및 브라우저 라우팅 (0) | 2021.12.27 |
---|---|
[REACT] 11_상세페이지 작성 2 : 리덕스 상태관리 (0) | 2021.12.27 |
[REACT] 9_상세페이지 브라우저 라우팅 (0) | 2021.12.27 |
[REACT] 8_브라우저 라우터 준비 및 상세페이지 라우팅 (0) | 2021.12.27 |
[REACT] 7_더보기 버튼 구성 및 기능구현 (0) | 2021.12.27 |