Hook 사용예제: useScroll, useFullScreen

Hyun·2021년 9월 21일
0

리액트 훅

목록 보기
12/14
post-thumbnail

useScroll

스크롤을 사용할 때, 현재 위치한 x, y좌표값의 조건에 따라 색상이 바뀌는 기능을 구현하였다.

...
const useScroll = () => {
  const [state, setState] = useState({
    x: 0,
    y: 0
  });
  const onScroll = (event) => {
    setState({y: window.scrollY, x: window.scrollX});
  }
  
  console.log(state);//check point!!! 
  
  useEffect(()=> {
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, [])
  return {state};
}

const App = () => {
  const {state} = useScroll();
  const x = state.x; const y = state.y;
  return(
    <div className="App" style={{width:"1000vh", height: "1000vh"}}>
     <h1 style={{ position: "fixed", color: y > 100 && x > 300 ? "red" : "blue"}}>Hi</h1>
    </div>
  )
}

export default App;

useScroll함수를 코딩하면서 현재 scroll의 좌표를 확인하고 싶어 onScroll함수안에 console.log(state);를 구현했었다.

하지만 state가 계속 초기값으로 출력되길래 몇 시간 동안 구글링과 stackoverflow, 오픈카톡을 돌아다녔다.

알아낸 결과로는 onScroll함수가 실행되고 있는 동안은 setState가 실행되도 상태값(state)이 즉시 update되지 않는다는 것이다.

useState의 상태값 변경함수는 배치라는 개념이 적용되는데, 배치는 효율적인 성능을 위해 여러 개의 state값을 하나의 리렌더링으로 묶는것이다.

따라서 또 다른 상태값 변경 함수가 나오면 배치로 묶어야 하기 때문에 setState가 호출된 시점에서 바로 상태값(state)이 update되지 않는 것이다.

onScroll함수가 호출되고 나서 console.log(state); 했을 때 위 이미지와 같이 정상적으로 state가 출력되는 것을 볼 수 있다 :)

useFullScreen

Make Full 버튼을 눌렀을 때 full screen을 구현하고 Exit Full 버튼을 눌렀을 때 exit screen하는 기능을 구현하였다.

...
const useFullScreen = (callback) => {
  const element = useRef();
  const triggerFull = () => {
    if(element.current){
      element.current.requestFullscreen();
      if(callback && typeof callback === "function"){
        callback(true);
        }
      }
    };   
  const exitFull = () => {
    document.exitFullscreen();
    if(callback && typeof callback === "function"){
        callback(false);
      }
  }
  return {element, triggerFull, exitFull}
}
//Fullscreen을 요청할땐 element와 함께 requestFullscreen을 사용하고,
//Fullscreen을 빠져나올땐 document를 사용한다.
const App = () => {
  const onFullS = (isFull) => {
    console.log(isFull ? "we are full" : "We are small");
  }
  const {element, triggerFull, exitFull} = useFullScreen(onFullS);
  return(
    <div> 
      <div ref={element}>
        <img src="https://thediplomat.com/wp-content/uploads/2018/04/sizes/td-story-s-2/thediplomat-12340397434_e186b8001a_k.jpg" alt=""/>
        <button onClick={exitFull}>Exit Full</button>
      </div>
     <button onClick={triggerFull}>Make Full</button>
    </div>
  )
}

export default App;

before

after

img 자체를 fullscreen하는 것보다 img를 감싸고 있는 div태그를 fullscreen하는게 나은 것 같다.

profile
better than yesterday

0개의 댓글