지금까지는 @media all and (max-width: ~)를 통해 반응형 웹을 만들고 있었다.
const NightSky = styled(NightSkyBackground)`
height: 100vh;
@media all and (max-width: 1200px){
height: 180vh;
}
`;
보통 이런 방법으로 하는게 일반적이지만 나는 아래와 같은 컴포넌트를 사용하고 있었다.
const NightSkyBackground = ({ height }) => {
//...
return (
<SkyContainer height={height}>
<StarsContainer>
{randomStars}
</StarsContainer>
</SkyContainer>
)
}
const SkyContainer = styled.div`
position: relative;
display: flex;
height: ${(props) => props.height || '100vh'};
background-color: #ffffff;
background: linear-gradient(#9A92C9, #7B85B7, #4659A9, #2C2C60);
background-size: 200% 200%;
opacity: 1;
animation: ${Gradient} 60s ease-in-out infinite;
overflow: hidden;
`;
//...
이 컴포넌트는 화면의 배경을 담당하고 있었는데, 다른 페이지에도 쓰여서 이 코드를 마음대로 수정할 수는 없었다. 그리고 컴포넌트에 props로 height를 전달해줘야하기 때문에 media를 사용할 수 없었고, 다른 방법을 찾아야만 했다.
그래서 생각한 방법은 실시간으로 윈도우 너비를 불러와서 윈도우 크기가 1200px 이하로 줄어들면 조건부로 다른 컴포넌트를 실행하는 거였다. 먼저 작성한 코드는 이거.
const isMobile = width <= 1200;
//...
return (
//...
{isMobile
? <NightSkyBackground height={'180vh'} />
: <NightSkyBackground height={'100vh'} /> }
//...
)
일단 isMobile을 만들어놓고 1200이하면 heigh를 180vh로 전달, 그 외는 100vh으로 전달하는 방식이었다.
마침 구글에 검색해보니 같은 방식을 적용한 사람이 있었다.
const [width, setWidth] = useState(window.innerWidth);
const isMobile = width <= 1200;
const handleResize = debounce(() => {
setWidth(window.innerWidth);
}, 200);
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
그래서 코드를 가져왔다. 여기서 debounce는 화면의 크기가 1px이라도 변경될 때마다 호출되다보니 아무래도 과부하가 올 수 있기에 그걸 방지하고자 적용하였다고 한다.
와중에 마주친 오류
'debounce' is not defined
이럴 때 index.html에 아래의 스크립트 태그를 추가해주면 된다고 한다.
<script src="http://benalman.com/code/projects/jquery-throttle-debounce/jquery.ba-throttle-debounce.js"></script>
하지만 나는 react로 작성하고 있고, index.html이 없다. index.js만 있을 뿐.
그래서 script 태그를 적용하려고 다시 찾아봤다.
그 방법은 아래와 같다.
//hook/useScript.js
import { useEffect } from 'react';
const useScript = url => {
useEffect(() => {
const script = document.createElement('script');
script.src = url;
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
}, [url]);
};
export default useScript;
//today.js
import useScript from 'hooks/useScript';
const today = () => {
useScript('http://benalman.com/code/projects/jquery-throttle-debounce/jquery.ba-throttle-debounce.js');
// rest of your component
}
근데 이렇게 하고 코드를 적용하려고 해봤지만 여전히 오류가 났다.
const handleResize = $.debounce(() => {
setWidth(window.innerWidth);
}, 200);
$.를 붙여보라고 하길래 붙여도 봤더니 '$' is not defined라고 한다. 뭘까?
그래서 브라우저 resize 글에 참조한 블로그 목록이 있길래 들어가봤다.
이 때 발견한 한 문장
똑같이 lodash에서 debounce를 import 해온 후에 사용한다.
debounce를 처음 사용해봤기에 lodash에서 import 해와야한다는 것도 몰랐다.
단지 설명을 보고 마지막 이벤트를 불러온다라는 것만 알고 있었을 뿐.
그래서 일단 lodash를 설치했다.
npm i --save lodash
설치 후 import 해와야 사용할 수 있으니 아래와 같이 import 해주고 debounce 앞에 언더바를 붙여줬다.
import _ from 'lodash';
const handleResize = _.debounce(() => {
//...
그랬더니 작동해요ㅠㅠ
참고자료
https://divheer.tistory.com/247
[React] resize 이벤트로 브라우저 크기에 따라 javascript 적용하기
CSS와 관계없이 브라우저의 width에 따라 컴포넌트 내에서 javascript를 다르게 적용하기 위해 resize 이벤트를 사용했다. resize 이벤트 const [width, setWidth] = useState(window.innerWidth); const isMobile = width { setWid
divheer.tistory.com
https://stackoverflow.com/questions/37730628/typeerror-debounce-is-not-a-function
TypeError: $.debounce is not a function
I am using this code: function resizeJquerySteps() { $('.wizard .content').animate({ height: $('.body.current').outerHeight() }, 'slow'); } $(window).resize($.debounce(250,
stackoverflow.com
https://stackoverflow.com/questions/34424845/adding-script-tag-to-react-jsx
Adding script tag to React/JSX
I have a relatively straightforward issue of trying to add inline scripting to a React component. What I have so far: 'use strict'; import '../../styles/pages/people.scss'; import React, { Compon...
stackoverflow.com
[React] 브라우저 크기 감지, throttle, debounce
바로 직전 포스팅에서 antd 그리드를 이용해서 브라우저 화면 사이즈에 따라 반응하는 페이지를 만들어 보았다. 정확히 768px에 바뀌는지 보려고 현재 화면의 너비를 리액트 컴포넌트에 띄워주려
9yujin.tistory.com
댓글