useEffect 함수 안에 보면 위에 선언한 callback함수와 option을 deps로 넣어준 것을 볼 수 있는데,
조금 더 자세히 알아보면
※ Intersection Oberver 첫 번째 deps : callback()
- callback : 타겟 엘리먼트가 교차되었을 때 실행할 함수
※ Intersection Oberver 두 번째 deps : root, rootMargin, threshold
- root
default : null, 브라우저의 viewport
교차영역의 기준이 될 root 엘리먼트. observer의 대상으로 등록할 엘리먼트는 반드시 root의 하위 엘리먼트여야 한다.
- rootMargin
default : '0px 0px 0px 0px'
root 엘리먼트의 margin.
- threshold
default : 0
0.0부터 1.0 사이의 숫자 혹은 이 숫자들로 이루어진 배열로, 타겟 엘리먼트에 대한 교차 영역 비율을 의미한다.
0.0의 경우 타겟 엘리먼트가 교차영역에 진입했을 시점이고, 1.0의 경우 타겟 엘리먼트 전체가 교차영역에 들어왔을 때의 observer를 실행하는 것을 의미한다.
다시 한 번 코드를 살펴보면
useEffect(() => {
let observer;
if (target) {
// callback 함수, option
observer = new IntersectionObserver(onIntersect, {
threshold: 0.4,
});
observer.observe(target); // 타겟 엘리먼트 지정
}
return () => observer && observer.disconnect();
}, [target]);
target 엘리먼트로 지정한 target State가 첫 렌더링 때 생성될 것이고, 첫 렌더링 때와 이 target의 변경이 감지될 때 useEffect가 실행된다. callback 함수로는 위에 선언한 onIntersect 함수이고, option으로 threshold : 0.4를 지정했다.
const onIntersect = async ([entry], observer) => {
if (entry.isIntersecting && !isLoding) {
observer.unobserve(entry.target);
setIsLoding(true);
// 데이터를 가져오는 부분
setIsLoding(false);
observer.observe(entry.target);
}
};
접속하는 해상도에 따라 컴포넌트 자체가 달라져야 할 상황에는 결국 모바일 전용웹을 구축하고 모바일 이외의 해상도(태블릿, 중소형 모니터) 접속웹을 반응형으로 구축해야 할텐데, 해상도에 따라 페이지 자체가 바뀌거나(path) 달라지는 컴포넌트들의 개수가 많아지면 웹을 나눠서 구축하는 것이 좋겠지만, 페이지를 그대로 사용하고 달라지는 컴포넌트들의 개수가 별로 없을 경우에는 접속하는 userAgent에 따라 해당 컴포넌트만 달라지게끔 하는 것이 좋을 수도 있다고 생각했다. 구글링을 한 결과 2가지의 방법을 찾아냈다.
1. react-device-detect
첫번째는 react-device-detect라는 npm 모듈을 이용하는 방법이다. 먼저 모듈을 설치하자.
$ npm install react-device-detect --save
달라져야 할 컴포넌트에 다음과 같이 import 한다.
import {
BrowserView,
MobileView,
isBrowser,
isDesktop,
isMobile
} from "react-device-detect";
import 한 변수의 값에 따라 다른 컴포넌트를 return 할 수 있다. ( 모바일일 경우 )
import {isMobile} from 'react-device-detect';
renderContent = () => {
if (isMobile) {
return <div> This content is unavailable on mobile</div>
}
return <div> ...content </div>
}
render() {
return this.renderContent();
}
특정 브라우저가 아닐 경우 다음과 같이 지원하지 않는다는 메세지를 줄 수도 있다.
import {isIE} from 'react-device-detect';
render() {
if (isIE) return <div> IE is not supported. Download Chrome/Opera/Firefox </div>
return (
<div>...content</div>
)
}
특정 Component에서 쓰이는 css는 컴포넌트와 이름이 같은 css 파일을 만들어서 import 할 수 있다.
예를들어 Components/Button 폴더 안에 index.js, Button.module.css 파일이 있다고 가정할 때 아래와 같이 사용할 수 있다.
Components/Button/Button.module.css
/*
You do not need to worry about .error {} colliding with any other `.css` or
`.module.css` files!
*/
.error {
color: white;
background-color: red;
}
Components/Button/index.js
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
// Note how the "error" class is accessed as a property on the imported
// `styles` object.
className={styles.error}
>
Destroy
</button>
)
}