크로스 브라우징 이슈를 해결하기 위한 css reset
브라우저의 호환성을 위한 기본 스타일을 제거하기 위한 작업
아래 코드 외에도 reset css를 검색하면 다양하게 나옴
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
ref
를 이용해 해당 DOM요소 접근하기 페이지가 렌더링될 때 아이디 input 태그에 foucs가 됨
import { useEffect, useRef } from "react";
import "./App.css";
function App() {
const idRef = useRef("");
// 렌더링이 될 때
useEffect(() => {
idRef.current.focus();
}, []);
return (
<>
<div>
아이디 : <input type="text" ref={idRef} />
</div>
<div>
비밀번호 : <input type="password" />
</div>
</>
);
}
export default App;
re-render의 발생 조건
1. 컴포넌트에서 state가 변경 될 때
2. 컴포넌트가 받아온 props가 변경 될 때
3. 부모 컴포넌트가 re-render된 경우 자식 컴포넌트도 re-render된다.
불필요한 렌더링을 발생하지 않도록 최적화하는 대표적인 방법
1. memo(React.memo) : 컴포넌트를 캐싱
2. useCallback : 함수를 캐싱
3. useMemo : 값을 캐싱
캐싱 : 캐시는 컴퓨터 과학에서 데이터나 값을 미리 복사해 놓는 임시 장소
memo
가 컴포넌트를 memoization 했다면, useCallback()
은 인자로 들어오는 함수 자체를 memoization 한다.
memo
를 통해 Box1
컴포넌트를 memoization 했음에도 re-render 발생
why? → 우리가 함수형 컴포넌트를 사용하기 때문이고 App.jsx가 리렌더링 되면서
const onInitButtonClickHandler = () => {
initCount();
};
코드가 다시 만들어지기 때문입니다.
Box1.jsx
는 props가 변경됐다고 인식한다.//App.jsx
// 변경 전
const initCount = () => {
setCount(0);
};
// 변경 후
const initCount = useCallback(() => {
setCount(0);
}, []);
useCallback()
을 사용하고 나면 리렌더 방지
// count를 초기화해주는 함수
const initCount = useCallback(() => {
// !!Expected "[COUNT 변경] => 10에서 0으로 변경되었습니다."!!
console.log(`[COUNT 변경] => ${count}에서 0으로 변경되었습니다.`);
setCount(0);
}, []);
현재 카운트가 10일 때 초기화 버튼을 누른다면
콘솔에 "[COUNT 변경] => 10에서 0으로 변경되었습니다."!!
가 나타나길 기대함
그러나 예상과 다르게
COUNT 변경] => 0에서 0으로 변경되었습니다.
라는 결과가 찍힌다.
이러한 이유는 useCallback()
이 count
가 0일 때 시점을 기준으로 메모리에 함수를 저장했기 때문이다. 이를 방지하려면 dependency에 count
값을 추가하면 된다.
// count를 초기화해주는 함수
const initCount = useCallback(() => {
console.log(`[COUNT 변경] ${count}에서 0으로 변경되었습니다.`);
setCount(0);
}, [count]); //count추가
useMemo()
: value(값)을 캐싱한다.CASE 1에서는 onClick()
을 실행할 때마다 count
는 올라가지만, 매번 heavyWork()
함수가 다시 실행되기 때문에 딜레이 발생
why?→ re-render될 때마다 heavyWork()
가 실행되며, 이 함수는 100억 번의 연산을 수행하기 때문
CASE 2에서 useMemo()
를 사용하면 처음 렌더링할 때 한 번만 heavyWork()
가 실행되고, 그 값이 memoization 된다.
이후에는 dependency가 변경되지 않는 한 heavyWork()
는 다시 실행되지 않음