マークアップエンジニアがReactを使って簡単なアプリケーションを作った話

# はじめに
私は実務でReactはおろかVanilla JSすら書いたことありません（JSXは書いたことある）
jQueryチョットデキル、くらいのレベル感です。
今回作ったアプリケーションも、強い人達からしてみれば酷いものだと思います。
ですが、先日「[ヘタクソなコードを書いてもいい](https://satoru-takeuchi.hatenablog.com/entry/2021/07/11/230232)」という記事を読み、内容に感銘を受けたので今回公開まで至りました。

# 私のスキルセット
HTML, CSS（マークアップエンジニアなので一応実務レベル）
JavaScript（Class構文、非同期処理は雰囲気）

# 作ったもの
目覚ましアプリ
[Alarm App](https://elated-jennings-a0bef5.netlify.app/)（iOSでは音が鳴りません）
![alarm_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3443/105a0297-3b7a-d336-624b-a00b5b845021.png)


# 書いたコード

```App.js

import React, { useState, useEffect } from 'react';
import sound from './sound/piano-without-melody-short-loop-60-bpm.mp3';
import Alarm from './components/Alarm';
import styled from 'styled-components';
import './App.css';

const alarmSound = new Audio(sound);
alarmSound.loop = true;

let dateMessage = {
  images: '',
  text: ''
}

const App =()=> {
  const [showTime, setShowTime] = useState(new Date());
  const [time, setTime] = useState('');
  const handleTime =(e)=> setTime(e.target.value);
  const [alarmTime, setAlarmTime] = useState('');
  const handleAdd =()=> {
    const newAlarm = time;
    setAlarmTime(newAlarm);
  }

  const stopSound =()=> {
    alarmSound.pause();
    alarmSound.currentTime = 0;
  }

  useEffect(() => {
    const timer = setInterval(()=> {
      setShowTime(new Date());
    }, 1000);
    return ()=> clearInterval(timer);
  }, []);

  const nowTime = showTime.toLocaleTimeString([],{hour: '2-digit', minute:'2-digit'});
  const nowTimeHour = showTime.toLocaleTimeString([],{hour: 'numeric'});
  const nowTimeHourNumber = parseFloat(nowTimeHour);

  useEffect(()=>{
   if(nowTime === alarmTime){
     alarmSound.play();
   }
  }, [nowTime, alarmTime]);

  useEffect(()=>{
    if(nowTimeHourNumber >= 6 && nowTimeHourNumber <= 11) {
      dateMessage = {
        images: 'https://source.unsplash.com/-G3rw6Y02D0',
        text: 'Good Morning'
      }
    }
    else if(nowTimeHourNumber >= 12 && nowTimeHourNumber <= 18){
      dateMessage = {
        images: 'https://source.unsplash.com/8GVuQUmZW8Y',
        text: 'Good Afternoon'
      }
    }
    else {
      dateMessage = {
        images: 'https://source.unsplash.com/VZxNq9GytpQ',
        text: 'Good Evening'
      }
    }
  }, [nowTimeHourNumber]);


  return (
    <Main style={{backgroundImage: `url(${dateMessage.images})`}}>
      <Alarm dateMessage={dateMessage} nowTime={nowTime} time={time} handleTime={handleTime} handleAdd={handleAdd} stopSound={stopSound} alarmTime={alarmTime} />
    </Main>
  );
}

const Main = styled.main`
  height: 100vh;
  width: 100%;
  background-size: cover;
`
export default App;

```

```/components/Alarm.js

import styled from 'styled-components';

const Alarm =(props)=> {
  const {nowTime,time, handleTime, handleAdd, stopSound, alarmTime, dateMessage} = props;
  return(
      <Content>
        <Message>{dateMessage.text}</Message>
        <DefaultText>The current time is</DefaultText>
        <TimeText>{nowTime}</TimeText>
        <DefaultText>Please, set the alarm</DefaultText>
        <SetTime type="time" value={time} onChange={handleTime} />
        <ButtonArea>
          <SetButton type="submit" onClick={handleAdd}>SetAlarm</SetButton>
          <SetButton type="submit" onClick={stopSound}>StopAlarm</SetButton>
        </ButtonArea>
        <TimeText>{alarmTime}</TimeText>
        <Credit>Music By <a href="https://freesound.org/people/josefpres/">josefpres</a></Credit>
      </Content>
  )
}

const Content = styled.div`
  display: block;
  max-width: 800px;
  margin: 0 auto;
  color: #fff;
  padding-top: 30px;
  text-align: center;
`

const Message = styled.h2`
  font-size: 45px;
  text-shadow: 1px 0 2px #333;
`

const DefaultText = styled.p`
  margin-top: 20px;
  font-size: 20px;
  text-shadow: 1px 0 2px #333;
`

const TimeText = styled.p`
  font-size: 30px;
  margin-top: 30px;
  text-shadow: 1px 0 2px #333;
`

const SetTime = styled.input`
  border: none;
  padding: 5px;
  margin-top: 20px;
`

const ButtonArea = styled.div`
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 30px;
`

const SetButton = styled.button`
  border: none;
  font-size: 18px;
  border-radius: 5px;
  padding: 5px 10px;
  cursor: pointer;
  background-color: #fff;
`

const Credit = styled.p`
  font-style: italic;
  font-size: 16px;
  margin-top: 20px;
  a {
    color: #fff;
  }
`
export default Alarm;
```

使用した音源は[freesound](https://freesound.org/)というサイトからダウンロードしました。


# アプリケーションを作るまで、どうやって勉強したか
けっこう様々な教材に手を出しましたが、私みたいにあまりJavaScriptがそこまでレベル高くない人だと、Udemyの「[モダンJavaScriptの基礎から始める挫折しないためのReact入門](https://www.udemy.com/course/modern_javascipt_react_beginner/)」が分かりやすかったです。
あと書籍だとKindle限定ですが、「[はじめてさわるReact & JavaScript](https://www.amazon.co.jp/gp/product/B09693ZJCV/ref=dbs_a_def_rwt_bibl_vppi_i2)」とかボリュームも少なく、一つのアプリを作るまで挫折せずにやりきれる感じが良いと思いました。

# iOSで音が鳴らない問題
私の作った目覚ましアプリは自動再生にあたるので、iOSのSafariのポリシーに引っかかり音を鳴らすにはさらに音を鳴らすためのボタンを作らなければいけなくなりました。

【参考記事】
[Safariで動画と音声が再生されない場合の解決方法](https://bagelee.com/programming/safari-video-audio-action/)
[iPadのSafariで音声を自動再生っぽく見せる方法](https://qiita.com/mimickn/items/1b8d0ad15843ff2f8406)

「アラーム」という名前でアプリを作っているので、わざわざ音を鳴らすためのボタンを作ること自体が本末転倒な気がしたので、iOSは切り捨てる事にしました（何か良い知恵があれば教えていただけると幸いです）

# おわりに
今回ちゃんと自分でWebアプリを作ること、そしてQiitaに記事を書くこと両方が初めてです。
私よりも優れているのに一歩踏み出せない人が「この程度の記事でも良いんだ」と思って、踏み出すきっかけになればいいなと思っています。




ちなみにお仕事募集中です :bow: