---
# System prepended metadata

title: Landscape-full-screen (React Hook)
tags: [Egret]

---

# Landscape-full-screen (React Hook)

:::info
index.html (不重要，主要邏輯在下方 index.js)
```htmlmixed=
// 宣告一個 root 標籤
<div id="root"></div>
```
:::

#### useEffect
你可以先粗略理解為 render 結束後的 callback

#### useState
你可以先粗略理解為 class 底下的 property

:::success
index.js
```jsx=
import React, { useEffect, useState, useRef } from 'react';
// 渲染方法
import { render } from 'react-dom';
import './style.css';

const isPortrait = () => (window.innerWidth < window.innerHeight);

const App = () => {
  // 設定 showSwipeUp(boolean) 預設值為 false
  const [ showSwipeUp, setShowSwipeUp ] = useState(false);
  
  // game-content 設定在 css，hide 設定在 css -> display: none
  const gameContentClasses = showSwipeUp ? 'game-content hide' : 'game-content';
  
  // swipe-up 設定在 css，show 設定在 css -> display: block
  const swipeUpClasses = showSwipeUp ? 'swipe-up show' : 'swipe-up';
  
  // 渲染完的 callback
  useEffect(() => {
    // 比較短的為高
    const screenHeight = Math.min(window.screen.width, window.screen.height);
    // 檢查 toolbar 是否顯示中 
    const onCheckSwipeUp = () => {
      const show = screenHeight - window.innerHeight > 40;
      // 設定 showSwipeUp = show
      setShowSwipeUp(show);
    }
    // 100 毫秒檢查一次 toolbar 是否顯示中
    setInterval(onCheckSwipeUp, 100);
    
    // 下次 effect 執行前，清除 onCheckSwipeUp Interval，避免重複呼叫 Interval
    return () => {
      clearIntrerval(onCheckSwipeUp);
    }
  // 此參數決定 effect 調用時機
  // 預設是每次渲染後都會執行
  // [] 空陣列，表示只在此組件被載入時執行一次
  }, []);
  
  // 渲染完的 callback
  useEffect(() => {
    const onResize = () => {
      // keep scroll to botoom at portrait mode.
      // 當在 landscape 時須設定為 0, 才能讓 swipe up div 在正確位置出現
      const offsetY = isPortrait() ? 9999 : 0;
      window.requestAnimationFrame(() => {
        window.scrollTo(0, offsetY);
      });
    }
    onResize();
    // 監聽視窗尺寸變動事件
    window.addEventListener('resize', onResize);
    // 下次 effect 執行前，清除 listener，避免重複監聽事件
    return (() => {
      window.removeEventListener('resize', resize);
    });
  // 此參數決定 effect 調用時機
  // 預設是每次渲染後都會執行
  // [] 空陣列，表示只在此組件被載入時執行一次
  }, []);

  // 渲染結構
  return (
    <div>
      // 渲染 game-content(不重要)
      <GameCanvas className={gameContentClasses}/>
      // 渲染 swipe up 字樣
      <div className={swipeUpClasses}>
        <span>swipe up</span>
      </div>
    </div>
  );
}

// 渲染 App 至 root 這個節點(root 被定義在 index.html)
render(<App />, document.getElementById('root'));

```
:::

:::info
GameCanvas.js
```jsx=
import React, { useEffect, useRef } from 'react';
const GameCanvas = ({ className }) => {
  const canvasRef = useRef(null);
  useEffect(() => {
    const onResize = () => {
      const canvas = canvasRef.current;
      const dpr = window.devicePixelRatio || 1;
      const rect = canvas.getBoundingClientRect();
      canvas.width = rect.width * dpr;
      canvas.height = rect.height * dpr;
      const ctx = canvas.getContext('2d');
      ctx.scale(dpr, dpr);
      ctx.font = '48px serif';
      ctx.fillText('Hello world', 10, 50);
    }
    onResize();
    window.addEventListener('resize', onResize);
    return (() => {
      window.removeEventListener('resize', resize);
    })
  }, []);

  return (
    <canvas ref={canvasRef} className={className}></canvas>
  )
}

export default GameCanvas;
```
:::

### 幫助理解 useState

```jsx=
import React, { useState } from 'react';

function Example() {
  // 宣告一個新的 state 變數，我們稱作為「count」。
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
```
等價於
```javascript=
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}
```

相關文章
[Tricky Solution](https://medium.com/@humanhighway/tips-about-how-to-make-a-landscape-fullscreen-webpage-in-ios-safari-2d6d0e94d324)
[React useState](https://zh-hant.reactjs.org/docs/hooks-state.html)
[React useEffect](https://zh-hant.reactjs.org/docs/hooks-effect.html)
[React useRef](https://zh-hant.reactjs.org/docs/hooks-reference.html)
[resize event](https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event)

###### tags: `Egret`