男子プログラマーになりたいやつ

未経験から一端のエンジニア目指し日々勉強中です。

React 基礎編

React 基礎編 f:id:TomozQ:20201103184527j:plain

React備忘録

目次
  • ReactDOM.render( )
  • JSX
  • Component




今回はReact.jsの記事になっています。


Reactの導入についてはいろんなとこで紹介されているので今回は省略させてもらいます。

今回はこんなのを作っていこうと思います。

f:id:TomozQ:20201103182930g:plain

各色がクリックされる度にトータルの数が増えていく、というような機能ですね。

では見ていきましょう。

ReactDOM.render( )

まずはベースとなるファイルです

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/styles.css">
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>
  <body>
    <script>

    </script>
  </body>
</html>


headタグ内にあるscriptタグ3つはReactのCDNを使用するための記述です。
そして、一般的なjsと同じようにbodyタグ内にscriptタグを用意し、スクリプトを書いていきます。

・・・

今思ったけどこの記事めちゃめちゃ長くなるかも・・・



まあ、やっていきましょう。

まずは処理全体を即時関数で囲いたいので、ES6のアロー関数で書いていきましょう。

ここからはbodyタグ内のみ書いていきますね。

<body>
  <script type="text/babel">
    (() => {
    
    })();
  </script>  
</body>

即時関数とは無名関数を定義と同時に実行する関数のことです。

補足ですが、scriptタグのtype属性がtext/babelとなっています。これはhtmlファイル9行目、スクリプトタグ3つ目のbabelというライブラリを使用するために書いています。
babelを用いることで、JSXJavaSvriptの新しい記法を使うことができます。

次にUIを表示する領域を作っていきます。

まずはdiv要素を作ります

<body>
  <div id='root'></div>
  <script type="text/babel">
    (() => {
    
    })();
  </script>  
</body>

そしてReactで作った部品を描画していきます。

<body>
  <div id='root'></div>
  <script type="text/babel">
    (() => {
      ReactDOM.render();
    })();
  </script>  
</body>


このように関数内でReactDOM.render();とします。
次に第一引数に描画したいUIをJSXという記法を用いて書き、第二引数にはそのUIをどこに描画したいのかを記述します。

(() => {
        ReactDOM.render(
          <p>Hi!</p>,
          document.getElementById('root')
        );
      })();


このように第一引数はHTMLと同じように要素を書きます。
第二引数ではjsの書き方で、idがrootの要素を取得しています。

なので今回の場合は

p要素のHi!という文字列を、 getElementById で取得したidがrootの要素に描画するという処理になっています。 f:id:TomozQ:20201103181607p:plain


JSX

JSXには{ }を使用することでJavaScriptを埋め込むことができます。

ではJSXをもう少し詳しく見ていくために、定数を定義し、埋め込みます。

(() => {
        const name = 'TomozQoo'
        ReactDOM.render(
          <p>Hi!{name}</p>,
          document.getElementById('root')
        );
      })();


{ }内をnameとしてJavaScriptを埋め込んでいます。 f:id:TomozQ:20201103181551p:plain

ちゃんと表示されていますね。

ちなみにメソッドもちゃんと使用することができます

(() => {
      const name = 'tomozqoo'
      ReactDOM.render(
        <p>Hi!{name.toUpperCase()}</p>,
        document.getElementById('root')
      );
    })();


f:id:TomozQ:20201103181538p:plain { }内でtoUpperCase( )とすることで全て大文字で出力されていますね。

そして、注意点なのですが、JSXで渡せる要素は1つという決まりがあります。

なので

(() => {
      const name = 'tomozqoo'
      ReactDOM.render(
        <p>Hi!</p>,
        <p>{name.toUpperCase()}</p>,
        document.getElementById('root')
      );
    })();

このようにp要素を2つ渡そうとするとエラーが出てしまいます。

f:id:TomozQ:20201103181524p:plain

今回のようにp要素を2つ渡したい場合には

(() => {
      const name = 'tomozqoo'
      ReactDOM.render(
        <div>
          <p>Hi!</p>
          <p>{name.toUpperCase()}</p>
        </div>,
        document.getElementById('root')
      );
    })();

このように1つの要素で囲ってあげる必要があります。

結果はこうです。

f:id:TomozQ:20201103181506p:plain

またHTMLには閉じタグがない要素もあります。

例えばhr要素なんかがそうですね。

(() => {
      const name = 'tomozqoo'
      ReactDOM.render(
        <div>
          <p>Hi!</p>
          <hr>
          <p>{name.toUpperCase()}</p>
        </div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>

f:id:TomozQ:20201103181454p:plain

そのまま書いてしまうと、このように閉じタグが無いよというエラーが出てしまいます。

その場合には

  <div>
    <p>Hi!</p>
    <hr/>
    <p>{name.toUpperCase()}</p>
  </div>,

このようにタグを閉じてあげればOKです。

f:id:TomozQ:20201103181412p:plain

ではさらに詳しくJSXを見ていきましょう。

<body>
  <div id="root"></div>
  <script type="text/babel">
    (() => {
      ReactDOM.render(
        <div></div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>

まずはクラスについてです。

HTMLだとクラスを指定するには

<div class='test'></div>

とかって書きますよね。

ただ、JavaScriptだとclassは予約語になっています。

class App{

}

こんな感じで使いますよね。

なのでJSXで要素のクラスを指定するには違う名前を使わなくてはならず、

classNameというのを使います。

<body>
  <div id="root"></div>
  <script type="text/babel">
    (() => {
      ReactDOM.render(
        <div className='box'></div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>


classと書いていたところをclassNameにしてあげるだけですね。

ではCSSでboxクラスの見た目を整えていきます。

.box{
  width: 100px;
  height: 100px;
  background: skyblue;
}

f:id:TomozQ:20201103181402p:plain

こんな感じ。ちゃんと適用されてますね。


また、直接スタイルを指定することもできます

ReactDOM.render(
        <div style={{width: 100, height: 100, backgroundColor: '#FF3333'}}></div>,
        document.getElementById('root')
      );


スタイルはオブジェクト形式で指定する必要があるので、まず{ }を書き、その中にプロパティが入ったオブジェクトを書いていきます。
そのため{{ }}の様になります。
また、属性についてはcamelCaseで書く必要があるのでCSSではbackground-colorとしているところJSXではbackgroundColorと書きます。
pxも省略することができます。

こんな感じですね。

f:id:TomozQ:20201103181352p:plain

では次にイベントを設定してみます。

この箱がクリックされたらアラートが出る様に設定してみましょう


まず関数を作ります。

<body>
  <div id="root"></div>
  <script type="text/babel">
    (() => {
      function showMessage(){
        alert('success!!');
      }

      ReactDOM.render(
        <div style={{width: 100, height: 100, backgroundColor: '#FF3333'}}></div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>

次にイベントを発火させる処理を書いていきましょう。

Reactでは要素に直接イベントを書くことが多い様です。

なので

<body>
  <div id="root"></div>
  <script type="text/babel">
    (() => {
      function showMessage(){
        alert('success!!');
      }

      ReactDOM.render(
        <div style={{width: 100, height: 100, backgroundColor: '#FF3333'}}
        onClick = 'showMessage'></div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>

としたいところですが、これだとエラーが出てしまいます。

f:id:TomozQ:20201103181338p:plain

String型ではなく、関数をちょうだい!!ってエラーですね

JavaSvriptの式は{ }で渡さなくてはいけないので

ReactDOM.render(
        <div style={{width: 100, height: 100, backgroundColor: '#FF3333'}}
        onClick = {showMessage}></div>,
        document.getElementById('root')
      );

とします。

こんな感じですね。

f:id:TomozQ:20201103181636g:plain


Component

ここではComponentと呼ばれる独自のタグを使って、様々な機能を追加していってみます。

下記はベースのコードです。

<body>
  <div id="root"></div>
  <script type="text/babel">
    (() => {
      ReactDOM.render(
        <div></div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>

では見ていきましょう。

ReactDOM.render(
        <Counter/>,
        document.getElementById('root')
      );

こんな書き方でコンポーネントは作ることができます。

1文字目は必ず大文字にしなくてはなりません。


次にコンポーネントを定義していきます。

JSの関数で定義します。

    (() => {
      function Counter(){

      }

      ReactDOM.render(
        <Counter/>,
        document.getElementById('root')
      );
    })();

こうですね

では中身を返す関数にしましょう。

  function Counter(){
    return <div>0</div>;
  }

f:id:TomozQ:20201103181322p:plain

ちゃんと0が表示されてますね!


Counterを増やしましょう

ReactDOM.render(
        <div>
          <Counter/>
          <Counter/>
          <Counter/>
        </div>,
        document.getElementById('root')
      );

JSXでは要素を一つしか返せないのでdivタグで囲ってあげます。

f:id:TomozQ:20201103181308p:plain

結果はこんな感じです。0が3つできました。


また、コンポーネントごと大枠の内容は一緒なんだけど微妙に変えたいということもできます。

その場合にはコンポーネントに属性をつけてあげます。

ReactDOM.render(
        <div>
          <Counter color='#FF3333'/>
          <Counter color='#FFFF55'/>
          <Counter color='#4689FF'/>
        </div>,
        document.getElementById('root')
      );

属性の名前は何でも大丈夫です。今回はcolorとして値に色を入れています。

そしたらコンポーネントでこの値を取ってみましょう

引数を指定します。

function Counter(props){
  return <div>{props.color}</div>;
}

f:id:TomozQ:20201103181253p:plain
引数をpropsとして{props.color}で要素のカラー属性の値を取得しています。

ここで注意なのですが、この引数である props は読み取り専用になっています。

なので

function Counter(props){
  props.color = 'red';
  return <div>{props.color}</div>;
}

としても

f:id:TomozQ:20201103181159p:plain

この様に、読み取り専用のプロパティだよというエラーが出てしまいます。


ではCounterが色を取得できたので、背景色を変えてみましょう。

(() => {
      function Counter(props){
        return <div style={{backgroundColor: props.color}}>0</div>;
      }

      ReactDOM.render(
        <div>
          <Counter color='#FF3333'/>
          <Counter color='#FFFF55'/>
          <Counter color='#4689FF'/>
        </div>,
        document.getElementById('root')
      );
    })();

f:id:TomozQ:20201103181148p:plain

こんな感じです。ちょっとだけそれっぽくなってきました!


では最後にちょろっとスタイルを整えます。

<body>
  <div id="root"></div>
  <script type="text/babel">
    (() => {
      function Counter(props){
        return <li style={{backgroundColor: props.color}}>0</li>;
      }

      ReactDOM.render(
        <div className='container'>
          <ul>
            <Counter color='#FF3333'/>
            <Counter color='#FFFF55'/>
            <Counter color='#4689FF'/>
          </ul>
        </div>,
        document.getElementById('root')
      );
    })();
  </script>
</body>

まずはJSXでCounterをリストにして、横並びにしたいのでdiv要素にcontainerというクラスをつけました。

そして返す要素をdiv要素からli要素に変更です。

f:id:TomozQ:20201103181137p:plain

こんな感じですね。


ではCSS

body{
  font-size: 16px;
  font-family: Verdana, sans-serif;
}

.container{
  width: 330px;
  margin: 20px auto;
}

.container ul{
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
}

.container li{
  width: 100px;
  height: 100px;
  line-height: 100px;
  text-align: center;
  cursor: pointer;
  user-select: none;
  border-radius: 50%;
  margin: 0 5px 10px 0;
}

CSSの説明は割愛します。

f:id:TomozQ:20201103181855p:plain

こんな感じです!



今回はここまで

続きは次回!

それではまた!