React Styled-component
* Styled-component를 사용하면 css파일이 없어도 된다
Styled-component 설치 : npm install styled-components
import styled from 'styled-components'
사용법 : let 변수명 = styled.button `내용` = 버튼을 만든것이고, 백틱으로 내용 설정
끌어와서 쓰려면 <변수명 />으로 사용
장점 : 다른 js파일에 관섭을 하지 않는다. 페이지 로딩 시간 단축
해당하는것도 props를 이용해서 특정 부분만 변경 가능


단점 : js파일이 복잡해짐.
React Lifecycle & useEffect
Lifecycle : 컴포넌트의 주기(장착, 업데이트, 삭제 시 실행 가능)
쓰는 방법 : useEffect(() => { 실행할 내용 })
* 페이지가 모두 렌더링 된 후 useEffect()안에 내용이 실행된다
쓰는 이유 : 연산이 오래 걸리는 경우, 같이 쓰게 될 경우, 페이지 로딩이 느려질 수도 있다
* 보통 시간이 오래걸리는 어려운 작업, 서버에서 데이터를 가져오는 작업 등을 useEffect()안에 사용
useEffect(() => { 실행할 내용 }, [변수]) : 변수가 변할때만 실행 하도록 설정
변수 없이 []만 쓸 경우, mount될때는 실행되지만, update가 될때는 실행안된다
* useEffect안에 return () => {실행할 내용} : 해당 내용은 useEffect가 실행되기 전에 실행
return을 쓰는 이유 : react는 재렌더링이 많기 때문에, 재렌더링 되었을때 기존의 것을 제거 등을 할 때 사용(충돌 방지)
* return은 mount될 때 실행 x, unmount 될 때 실행
setTimeout(함수, 시간) : 해당 시간이 지난후, 함수 실행
clearTimeout(타이머 변수명) : 해당 타이머를 제거
총정리
1. 재렌더링마다 코드 실행 하고 싶으면 : useEffect(() => {코드})
2. mount시 1회 코드 실행 하고 싶으면 : useEffect(() => {코드}, [])
3. unmount시 1회 코드 실행 or useEffect 실행 전 코드 실행 하고 싶으면 : useEffect(() => { return () => {코드} })
4. 특정 state 변경시에만 실행 하고 싶으면 : useEffect(() => {코드}, [변수])
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
function Detail(props){
let {id} = useParams();
let 찾은상품 = props.shoes.find(function(x){
return x.id == id
});
let [count, setCount] = useState(0);
//let [alert, setAlert] = useState(true)
let [num, setNum] = useState('');
useEffect(()=>{
if (isNaN(num) == true){
alert('그러지마세요')
}
}, [num])
// useEffect(() => {
// let a = setTimeout(() => {setAlert(false)}, 2000)
// console.log(2)
// return () => {
// console.log(1)
// clearTimeout(a);
// }
// }, [])
return(
<div className="container">
{
alert == true
? <div className="alert alert-warning">
2초 이내 구매시 할인
</div>
: null
}
{count}
<button onClick={() => {setCount(count+1)}}>버튼</button>
<div className="row">
<div className="col-md-6">
<img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
</div>
<div className="col-md-6">
<input onChange={(e) => {setNum(e.target.value)}} />
<h4 className="pt-5">{찾은상품.title}</h4>
<p>{찾은상품.content}</p>
<p>{찾은상품.price}원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
</div>
)
}
export default Detail;
실행 결과
React ajax
ajax로 GET/POST요청하려면 방법 3가지 = XMLHttpRequest, fetch(), axios
axios 라이브러리 설치 : npm install axios - import axios from 'axios'
axios.get('url') : url에 해당하는 데이터 불러옴
.then() : 해당하는 데이터 가져옴
.catch() : 가져오는데 실패하였을 때

* 여러개의 url에게 get요청을 보내고 싶을 때 : Promise.all([axios.get('url'), axios.get('url') , ...]).then()
* fetch()를 쓰게되면, json형식을 변환하는 과정이 필요하지만, axios는 자동으로 해준다
import { Container, Nav, Navbar } from 'react-bootstrap';
import './App.css';
import bg from './img/bg2.jpg';
import { useState } from 'react';
import data from './data.js';
import { Routes, Route, Link, useNavigate, Outlet} from 'react-router-dom'
import Detail from './routes/Detail.js'
import axios from 'axios'
function App() {
let [shoes, setShoes] = useState(data)
let navigate = useNavigate();
return (
<div className="App">
<Navbar bg="light" data-bs-theme="light">
<Container>
<Navbar.Brand href="#home">ShopShop</Navbar.Brand>
<Nav className="me-auto">
<Nav.Link onClick={() => { navigate('/')}}>Home</Nav.Link>
<Nav.Link onClick={() => { navigate('/detail') }}>Detail</Nav.Link>
</Nav>
</Container>
</Navbar>
<Routes>
<Route path='/' element={
<>
<div className='main-bg' style={{backgroundImage:'url(' + bg + ')' }}></div>
<div className='container'>
<div className='row'>
{
shoes.map(function(a, i){
return(
<Card shoes = {shoes[i]} i = {i}></Card>
)
})
}
</div>
</div>
<button onClick={() => {
axios.get('https://codingapple1.github.io/shop/data2.json')
.then((data) => {
console.log(data.data);
let copy = [...shoes, ...data.data];
setShoes(copy)
})
.catch(() => {
console.log('실패함')
})
}}>더보기</button>
</>
} />
<Route path='/detail/:id' element={<Detail shoes={shoes}/>} />
</Routes>
</div>
);
}
function Card(props){
return(
<div className='col-md-4'>
<img src={"https://codingapple1.github.io/shop/shoes" + (props.i+1) + ".jpg"} width="80%"></img>
<h5>{props.shoes.title}</h5>
<p>{props.shoes.price}</p>
</div>
)
}
export default App;
실행 결과
React 탭 UI
* if문을 쓰고 싶다면, 컴포넌트 사용
import React, { useEffect, useState } from "react";
import { Nav } from "react-bootstrap";
import { useParams } from "react-router-dom";
function Detail(props){
let {id} = useParams();
let 찾은상품 = props.shoes.find(function(x){
return x.id == id
});
let [alert, setAlert] = useState(true)
let [탭, 탭변경] = useState(0);
useEffect(() => {
let a = setTimeout(() => {setAlert(false)}, 2000)
console.log(2)
return () => {
console.log(1)
clearTimeout(a);
}
}, [])
return(
<div className="container">
{
alert == true
? <div className="alert alert-warning">
2초 이내 구매시 할인
</div>
: null
}
<div className="row">
<div className="col-md-6">
<img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
</div>
<div className="col-md-6">
<h4 className="pt-5">{찾은상품.title}</h4>
<p>{찾은상품.content}</p>
<p>{찾은상품.price}원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
<Nav variant="tabs" defaultActiveKey="link0">
<Nav.Item>
<Nav.Link onClick={() => {탭변경(0)}} eventKey="link0">버튼0</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => {탭변경(1)}} eventKey="link1">버튼1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => {탭변경(2)}} eventKey="link2">버튼2</Nav.Link>
</Nav.Item>
</Nav>
<TabContent 탭={탭}></TabContent>
</div>
)
}
function TabContent(props){
// if (props.탭 == 0) {
// return <div>내용0</div>
// } else if (props.탭 == 1) {
// return <div>내용1</div>
// } else if (props.탭 == 2) {
// return <div>내용2</div>
// }
return [<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][props.탭]
}
export default Detail;
실행 결과
React transition (전환 애니메이션)
전환 애니메이션 만드는법
1. 애니메이션 동작 전 className 만들기
2. 애니메이션 동작 후 className 만들기
3. className에 transition 속성 추가
4. 원할 때 2번 className 부착
* className은 여러개 넣고 싶을 때는 띄어쓰기로 구분한다
* automatic batching기능때문에, 효과를 주려면, setTimout() 사용
import React, { useEffect, useState } from "react";
import { Nav } from "react-bootstrap";
import { useParams } from "react-router-dom";
function Detail(props){
let {id} = useParams();
let 찾은상품 = props.shoes.find(function(x){
return x.id == id
});
let [alert, setAlert] = useState(true)
let [탭, 탭변경] = useState(0);
let [fade2, setFade2] = useState('')
useEffect(() => {
let a = setTimeout(() => {setAlert(false)}, 2000)
console.log(2)
return () => {
console.log(1)
clearTimeout(a);
}
}, [])
useEffect(() => {
setFade2('end')
return () => {
setFade2('')
}
})
return(
<div className={"containe start " + fade2}>
{
alert == true
? <div className="alert alert-warning">
2초 이내 구매시 할인
</div>
: null
}
<div className="row">
<div className="col-md-6">
<img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
</div>
<div className="col-md-6">
<h4 className="pt-5">{찾은상품.title}</h4>
<p>{찾은상품.content}</p>
<p>{찾은상품.price}원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
<Nav variant="tabs" defaultActiveKey="link0">
<Nav.Item>
<Nav.Link onClick={() => {탭변경(0)}} eventKey="link0">버튼0</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => {탭변경(1)}} eventKey="link1">버튼1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => {탭변경(2)}} eventKey="link2">버튼2</Nav.Link>
</Nav.Item>
</Nav>
<TabContent 탭={탭}></TabContent>
</div>
)
}
function TabContent(props){
let [fade, setFade] = useState('')
useEffect(() => {
let a = setTimeout(() =>{setFade('end')}, 100)
return () => {
clearTimeout(a)
setFade('')
}
}, [props.탭])
return (<div className={"start " + fade }>
{[<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][props.탭]}
</div>)
}
export default Detail;
실행 결과
'react' 카테고리의 다른 글
React 성능 개선 (개발자 도구 & lazy import, memo & useMemo, useTransition & useDeferredValue) (0) | 2024.06.05 |
---|---|
React if문 작성 패턴, localStorage, react-query, PWA(앱 실행), async (0) | 2024.06.03 |
React Bootstrap, 이미지 및 public폴더 사용, import & export, 라우터 (0) | 2024.05.31 |
React input, class (0) | 2024.05.30 |
React 컴포넌트, 동적 UI, 박복문(map), props(state 자식과 부모) (0) | 2024.05.30 |