-
글쓴이글
-
2021년 6월 7일 09:45 #10144
강성구참가자/*eslint-disable*/
import axios from 'axios';
import React, { useContext, useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router';
import { Navbar, Nav, NavDropdown, Jumbotron, TabContent } from "react-bootstrap";
/* 컴포넌트 파일 만들때는 import React 꼭 해야한다!! */
// useEffect작성과 동시에 import 자동완성됨
import styled from 'styled-components';
import './Detail.scss';
import {재고context} from './App.js';import { CSSTransition } from "react-transition-group";
// styled-component
// 컴포넌트에 직접 스타일 넣어서 스타일링하기
// css를 입혀놓은 컴포너트를 만들어서 쓴다(className 작명 필요없음)
let 박스 = styled.div'
padding : 20px;
';let 제목 = styled.h4'
font-size: 25px;
color : ${ props => props.색상 };
';function Detail(props) {
let
= useState(true);
let [inputData, inputData변경] = useState('');
let 재고 = useContext(재고context); // value에 해당하는 state를 재고라는 변수에 할당
// inputData라는 state가 변경이 되면 이 해당 컴포넌트가 재렌더링됨(전문용어로 update된다)
// 재렌더링될때마다 useEffect도 실행됨// useEffect가 실행되는 상황
// 1. 컴포넌트가 mount 됐을때,
// 2. 컴포넌트가 update 될 때, 특정코드를 실행할 수 있음
// ★★★ ★★★★★★★★★ ★★★
// Detail 컴포넌트 등장하자마자 useEffect 함수 ★★★ 무조건 1번은 수행 ★★★
// ★★★ ★★★★★★★★★ ★★★
let [누른탭, 누른탭변경] = useState(0);
let [스위치, 스위치변경] = useState(false);
useEffect(() => {axios.get();
// Detail 컴포넌트가 화면에 보일때(랜더링될 때), 또는 업데이트 될때 useEffect 실행됨
const 타이머 = setTimeout(() => { alert변경(false) }, 2000);
console.log('무조건 한번 실행');
// 타이머를 삭제하고 싶을 때를 위해 변수에 저장해서 사용
// return function () => { 실행코드 }. Detail 컴포넌트가 사라질때(Unmount될때) 실행할 코드.
// return 해석 : 퉤 뱉는다 의미가 아니라, 오른쪽의 코드를 실행하달라.
return function() { clearTimeout(타이머) }
},);
// useEffect 여러번 작성 가능. 수행순서는 하향식let history = useHistory();
let {id} = useParams(); /* object 자료형이 남음. {사용자가 입력한 URL파라미터들} */
let 찾은상품 = props.shoes.find( x => x.id === Number(id)); /* 타입 맞춰줘야함 */
return(
<div className="container">
<박스>{/* styled component */}
<제목 className="red"> Detail </제목>
{/* <제목 색상="blue">Detail</제목>
<제목 색상={"red"}>Detail</제목> */}
</박스><div style={{ padding:"15px" }}> { inputData } </div>
<input onChange={(e) => { inputData변경(e.target.value)}}/> {/* input에 입력된값 */}{/* UI 제작 끝 */}
{/* 항상 보이는 UI가 아니라면 삼항연산자로 켜졌다 꺼졌다 스위치처럼 만드는게 관습!! */}
{/* useState의 alert변수를 사용하기 위해 {} 써줘야함 */}{
alert === true
? <div className="my-alert"> {/* 쌩 HTML을 넣어줄수있다. 전에는 컴포넌트를 넣었었는데 */}
<p>재고가 얼마 남지 않았습니다.</p>
</div>
: null
}
<div className="row">
<div className="col-md-6">
<img src={"https://codingapple1.github.io/shop/shoes"+(parseInt(id)+1)+".jpg"} width="100%" />
</div>
<div className="col-md-6 mt-4">
<h4 className="pt-5">{찾은상품.title}</h4>
<p>{찾은상품.content}</p>
<p>{찾은상품.price}</p>
<Info 재고={props.재고} shoes={props.shoes}></Info><button className="btn btn-danger" onClick={ () => {
let new재고 = [...props.재고];
new재고[0] > 0 ? new재고[0] -= 1 : new재고[0] = 0
props.재고변경(new재고);
}}> 주문하기 </button>
<button className="btn btn-danger" onClick={ () => {
history.goBack(); // 1. useHistory 라는 훅 import. 2. useHistory() 훅 사용
// history.push('/'); push 써서 특정경로로 이동.
}}> 뒤로하기 </button>
</div>
</div>{/* 부트스트랩 Tab만들기 복붙 */}
<Nav className="mt-5" variant="tabs" defaultActiveKey="link-1">{/* mt : 부트스트랩이 기본제공하는class margin-top-5 */}
<Nav.Item>
<Nav.Link eventKey="link-0" onClick={ () => { 누른탭변경(0), 스위치변경(false) }}>Active</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link-1" onClick={ () => { 누른탭변경(1), 스위치변경(false) }}>Option 1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link-2" onClick={ () => { 누른탭변경(2), 스위치변경(false) }}>Option 2</Nav.Link>
</Nav.Item>
</Nav>
{/* 삼항연산자는 3개이상의 조건이 있을때 좋은게 아니다. */}
{/* {
누른탭 == 0
? <div>00</div>
: <div>11</div>
} */}{/* 애니매이션 주고 싶은걸 CSS컴포넌트로 감싸버린다. */}
{/* 각각 스위치(true일때만 적용), 클래스 작명, 0.5초동안 실행 */}
{/* ture / false값을 state로 저장해서 쓰자 */}
<CSSTransition in={스위치} className="wow" timeout={2000}>
<TabComponent 누른탭={누른탭} 스위치변경={스위치변경} />
</CSSTransition></div>
)
}function TabComponent(props){
useEffect( () => {
console.log('TabComponent안의 useEffect');
props.스위치변경(true);
});if (props.누른탭 === 0) {
return <박스><div>0번째 내용입니다.</div></박스> // styled component 먹인 사례 // 입장하자마자 0번째 내용으로만 뜨지?
} else if (props.누른탭 === 1) {
console.log('TabComponent안의 조건에 부합하는 값');
return <박스><div>1번째 내용입니다.</div></박스>
} else if (props.누른탭 === 2) {
return <박스><div>2번째 내용입니다.</div></박스>
}
}function Info(props) {
return (
<>
{/* {console.log(Number(props.id))} */}
{/* {console.log(props.shoes[Number(props.id)])} 해당 신발 번호에 맞게 번호나오는 코드 */}
<p> 재고 : {props.재고[0]} </p>
</>
)
}export default Detail;
///////////////////////////////////////
// import React from 'react';
// import { useParams } from 'react-router-dom';// function Detail(props){
// let { id } = useParams();
// let 찾은상품 = props.shoes.find(function(상품){
// return 상품.id === id
// });// return (
// <div className="container">
// <div className="row">
// <div className="col-md-6">
// <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" alt=""/>
// </div>
// <div className="col-md-6 mt-4">
// <h4 className="pt-5">{찾은상품.title}</h4>
// <p>{찾은상품.content}</p>
// <p>{찾은상품.price}원</p>
// <button className="btn btn-danger">주문하기</button>
// </div>
// </div>
// </div>
// )
// };// export default Detail;
질문1 :
누른탭이 1일 때 콘솔창에 아래처럼 4번이 반복됩니다.
TabComponent안의 조건에 부합하는 값
TabComponent안의 useEffect'
TabComponent안의 조건에 부합하는 값
TabComponent안의 useEffect'
TabComponent안의 조건에 부합하는 값
TabComponent안의 useEffect'
TabComponent안의 조건에 부합하는 값
TabComponent안의 useEffect'
이렇게 4번이 나오는데 왜 그런건지 궁금해서 질문올립니다.
질문 2. 코드와 같이
<Nav className="mt-5" variant="tabs" defaultActiveKey="link-1"> 처음 detail페이지에 들어갔을 때 1번 탭이 눌리게 default를 지정했습니다. 헌데 밑의 내용으로는 '1번째 내용입니다'가 아닌
0번째 내용입니다. 로 시작이 됩니다. 해결하고 싶은데 힌트좀 받을 수 있을까요?
2021년 6월 7일 10:49 #10147
강성구참가자질문 빠트린게 있어 하나 더 추가합니다
선생님과 똑같은 코드를 따라쳤지만 CSSTransition이 적용 안돼고 있습니다.
2021년 6월 7일 10:58 #10148
codingapple키 마스터3은 CSSTransition 컴포넌트로 싸맬 때 classNames 속성 오타인듯합니다
2는 defaultActive어쩌구 쓰려면 아마 부트스트랩 <Tab> 컴포넌트로 싸매야할걸요
1 은 저도 모르겟읍니다 그 컴포넌트 재렌더링이 4번 일어나는군요 왜일까요
2021년 6월 7일 14:09 #10157
강성구참가자{/* 부트스트랩 Tab만들기 복붙 */}
<Nav className=”mt-5″ variant=”tabs” defaultActiveKey=”link-1″>{/* mt : 부트스트랩이 기본제공하는class margin-top-5 */}
<Nav.Item>
<Nav.Link eventKey=”link-0″ onClick={ () => { 누른탭변경(0), 스위치변경(true) }}>Active</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey=”link-1″ onClick={ () => { 누른탭변경(1), 스위치변경(true) }}>Option 1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey=”link-2″ onClick={ () => { 누른탭변경(2), 스위치변경(true) }}>Option 2</Nav.Link>
</Nav.Item>
</Nav>선생님께서 작성하신 코드에서 스위치변경부분만 모두 true로 바꾼 코드입니다.
맨처음 스위치 state를 false로 만들었고 버튼을 눌렀을 경우 true로 바꿔주라는 의미로 해석이 됩니다.
그럼 해당 탭의 in={true}가 되며 정상적으로 CSSTransition이 적용되야 할것같은데 안되네요.
이유를 알수 있을까요? 다른 탭들은 버튼을 누르지도 않았으니 다른것들은 그대로 false라서 모두가 true라는 충돌은 안 일어날거 같다 정도까지만 생각이 뻗쳤습니다.
2021년 6월 7일 17:38 #10169
codingapple키 마스터그것은 실험해봐야겠지만 아마 1. state변경함수는 차례로 동작하지 않고 async하게 동작해서
2. 탭컴포넌트가 재랜더링되지 않아서 둘 중 하나의 이유일 것 같습니다
-
글쓴이글
- 답변은 로그인 후 가능합니다.