React 개발자 도구 & lazy import
개발자 도구
https://chromewebstore.google.com/ - react delveloper tools 검색 - 다운로드
* react로 만들어진 페이지만 확인 가능
F12 - Components = Element보다 좀더 편하게 확인 가능

F12 - Profiler = 성능저하되는 컴포넌트 범인 찾기

lazy import
Single Page Application 특징 : js파일 하나에 모든 코드를 다 쑤셔 넣는다. (사이즈가 크다)
따라서, 해당 페이지를 로딩할 때 필요하지 않는 import부분이 있으면,
그 부분은 lazy import()로 묶어준다

로딩 중일 때, 흰색 화면이 뜨기 때문에 그것을 방지하기 위해
Suspense를 import해주고, lazy import한 컴포넌트 부분을 <Suspense>로 감싸준다
import { Container, Nav, Navbar } from 'react-bootstrap';
import './App.css';
import bg from './img/bg2.jpg';
import { createContext, lazy, Suspense, useEffect, useState } from 'react';
import data from './data.js';
import { Routes, Route, Link, useNavigate, Outlet} from 'react-router-dom'
import axios from 'axios'
import { useQuery } from 'react-query';
//import Detail from './routes/Detail.js'
// import Cart from './routes/Cart.js'
const Detail = lazy(() => import('./routes/Detail.js'));
const Cart = lazy(() => import('./routes/Cart.js'));
export let Context1 = createContext()
function App() {
let obj = {name : 'kim'}
let [shoes, setShoes] = useState(data)
let [재고] = useState([10, 11, 12])
let navigate = useNavigate();
useEffect(() => {
localStorage.setItem('watched', JSON.stringify([]))
}, [])
let result = useQuery('작명', () => {
return axios.get('https://codingapple1.github.io/userdata.json').then((a) => {
console.log('요청됨')
return a.data;
})
})
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('/cart') }}>cart</Nav.Link>
</Nav>
<Nav className='ms-auto'>
{result.isLoading && '로딩중'}
{result.error &&'에러남'}
{result.data && result.data.name}
</Nav>
</Container>
</Navbar>
<Suspense fallback={<div>로딩중임</div>}>
<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={
<Context1.Provider value={{재고}}>
<Detail shoes={shoes}/>
</Context1.Provider >
} />
<Route path="/cart" element={<Cart></Cart>}></Route>
</Routes>
</Suspense>
</div>
);
}
function Card(props){
let navigate = useNavigate();
return(
<div className='col-md-4'>
<img onClick={() => {navigate('detail/' + (props.i))}} 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 memo & useMemo
자식 컴포넌트 재렌더링 막기
자식 컴포넌트 무거울 경우 계속 재렌더링 할 경우 속도가 저하될 수 있으므로,
재 렌더링 필요없는 경우면, memo(import 해줘야함)로 해당 컴포넌트를 감싸준다

* memo 원리 : memo로 된 함수의 props가 변할 때에는 재렌더링 된다
useMemo(함수) : 해당하는 페이지가 처음 로드 될때만 실행하고, 나머지는 실행하지 않는다
하지만 useEffect처럼 , [state] 를 통해 state가 변경될때도 실행 가능

import { Table } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import { increase, changeName} from "./../store/userSlice";
import { addCount } from "./../store.js";
import { memo, useMemo, useState } from "react";
function 함수(){
return 반복문 10억번;
}
let Child = memo( function(){
console.log("재렌더링됨")
return <div>자식임</div>
})
function Cart(){
let result = useMemo(() => {return 함수()}, [state])
let state = useSelector((state) => { return state })
let dispatch = useDispatch()
let [count, setCount] = useState(0)
return(
<div>
<Child count={count}></Child>
<button onClick={() => {setCount(count+1)}}>+</button>
<h6>{state.user.name} {state.user.age}의 장바구니</h6>
<button onClick={() => {dispatch(increase(10))}}>버튼</button>
<Table>
<thead>
<tr>
<th>#</th>
<th>상품명</th>
<th>수량</th>
<th>변경하기</th>
</tr>
</thead>
<tbody>
{
state.cart.map(function(a, i){
return(
<tr key={i}>
<td>{a.id}</td>
<td>{a.name}</td>
<td>{a.count}</td>
<td>
<button onClick={() => {
dispatch(addCount(a.id))
}}>+</button>
</td>
</tr>
)
})
}
</tbody>
</Table>
</div>
)
}
export default Cart;
React useTransition & useDeferredValue
useTransition
계산이 많아서 성능이 저하될 때, 해당하는 함수에 useTransition을 사용
동작 원리 : 코드 시작을 뒤로 늦춰서, 한꺼번에 코드를 처리할 때의 성능저하를 막아줌
사용 방법 : useTransition을 import 한다

계산이 복잡한 부분에 startTransition을 감싸준다

계산중(로딩중)일 때 true를 반환한다

useDeferredValue
useTransition과 마찬가지로 느린 컴포넌트 성능을 향상시켜줌
useDeferredValue(state명) : 복잡한 state가 변할때 성능 향상

'react' 카테고리의 다른 글
React api 로그인 (카카오톡, 구글, 네이버) (0) | 2024.11.11 |
---|---|
React 미디어쿼리 (@media) (0) | 2024.09.29 |
React if문 작성 패턴, localStorage, react-query, PWA(앱 실행), async (0) | 2024.06.03 |
React Styled-component, Lifecycle & useEffect, ajax, 동적 UI, transition) (0) | 2024.05.31 |
React Bootstrap, 이미지 및 public폴더 사용, import & export, 라우터 (0) | 2024.05.31 |