【React】とらゼミの「新・日本一わかりやすいReact入門」で学んでみた

React

React習得のために、progate、やっすんのYouTube、公式チュートリアルをやってみましたが、まだ自力で実装できる気がしないと思い、こちらのとらゼミさんのyoutubeがわかりやすそうだったのでやってみました!

ちなみに、 やっすんのyYouTube、公式チュートリアル は途中で挫折しています。

詳しい説明が無いので途中で何をやっているのかわからなくなり、自分にはダメでした…

今回こそはやりきって、実装に移りたいと思います!

とらゼミ動画を見て学んだことをまとめました。

Reactを使う理由

従来の、DOMを直接取得して変更を加える(再描画する)処理を行うとコストが高い。

この問題をReactが解決してくれる。

ビューの変更処理をブラウザでなくJavaScriptエンジンに任せることで、ブラウザの負荷を軽減する。

再描画をレンダリングという。

仮想DOMで差分のみ描画する。これにより必要な部分だけ書き換えることができる。

JSX

HTMLだけど、その中でJavaScriptが使えるイメージ。

なぜ使うのか

JavaScriptなので、最終的にはHTMLに変換されているが、JSXを使うことによってHTMLライクに書くことができる。

使わない場合、React.createElementといった構文をいちいち書かないといけなくなる。

特殊な構文

JSXは必ず階層構造とする。

つまり、returnの下の階層に並列で存在してはならない。

そのため、divタグで囲う。

しかし、無意味なdivタグは使いたくないといった場合には、

<React.Fragment>といった書き方もある。さらにこれは省略して<>こう空タグで記述することもできる。

環境構築

create-react-appを使うことで、SPA シングルページアプリケーションを構築できる!

以下のインストールが必要。

  • Homebrew
  • nodebrew
  • Node.js
  • npm これはNode.jsをインストールすれば勝手にインストールされる。

それぞれどんな役割のものか?

Homebrew

mac OSのバージョン管理

nodebrew

nodeのバージョン管理

Node.js

サーバー環境で動くJavaScriptであり 、ローカル環境でJavaScriptを動かすために必要。

npm

Node.jsのパッケージマネージャー

バージョン管理をしてくれる。

全てのインストールができたら、いよいよReactに!

$ npx create-react-app react-tutorial-torazemi

npxとは?

ネットワーク上にあるnpxのコマンドを実行する。

作成したディレクトリに移動

$ cd react-tutorial-torazemi

アプリの起動

$ npm start

これにより構築されたアプリはホットリロードに対応している。

ホットリロードとは何か?

ファイルを編集したら、サーバーが自動で更新される。

コンポーネントはClassとFunctional(関数)があるが、今後はFunctionalを使おう!

昔はClassでないとできないことがあったが、React Hooksの登場で、Functionalでも使えるようになった。

であれば、記述量の少ないFunctionalを使いたい。

ClassとFunctionalの違い

以下は同じ挙動になる。

Class

import React, {Component} from 'react';
class Button extends Component {
  render() {
    return <button>Say, {this.props.hello}</button>
  }
}
export default Button;

Functional

import React from 'react';     ←これは省略することも可能
const Button = (props) => {
  return <button>Say, {props.hello}</button>
};
export default Button;

コンポーネント

使う理由

  • 同じ記述をせず、再利用するため
    同じ役割はコンポーネントの呼び出しで実装する。
  • 1コンポーネント = 1ファイルとすることで、読みやすくなる

使い方

親と子に分かれて、子は呼び出される側になる。

子の側では、関数の定義とexportをする。

親の側では、importでの呼び出しと、JSX内で関数呼び出し

子の同じコンポーネントを使用して、親側で値を指定する。

役割(責務)ごとにコンポーネントを分ける。

export, importの種類

default(名前無し)と名前付きがある。

default export

アロー関数の場合
const Title = (props) => {
  return <h2>{props.title}</h2>
};
export default Title;
名前付き関数の場合
export default function Title(props) {
  return <h2>{props.title}</h2>
};

名前付きexport

export const addTax = (price) => {
  return Math.floor(price * 1.1)
}
export const ...

1ファイル1コンポーネントでない場合に、関数単位でexportする。

エントリポイントで使う。

default exportしたコンポーネントは、一度1つのファイルにまとめる。このまとめられたところをエントリポイントという。

慣例的にエントリポイントはindex.jsで作るようになっている。

名前付きimport

import {Content, Title} from "./index";

これにより、エントリポイントのindex.jsからContentとTitleコンポーネントがimportできる。

これを、まとめずに記述する場合、以下のようになる。

import Content from './Content'
import Title from './Title'

このように毎回、すべてのファイルで指定をしないといけないので手間

Hooksとは何か

stateを関数コンポーネントでも使えるようにしたもの。

従来はclassコンポーネントでしか使うことができなかった。

stateをなぜ使うのか

要素の書き換えをするため。

JavaScriptの考えでいくとDOMで直接書き換えたくなる。

しかし、Reactでそれをやると、仮想DOMというReactのメリットを活かすことができないため、そのような処理はしてはいけないことになっている。

そこでstateを使用する。

Reactコンポーネントが再描画(レンダリング)するきっかけは?

stateかpropsが変更されたとき。

useStateの使い方

useStateによるstateの宣言

const [state, setState] = useState(initialState)

それぞれの役割

state: 現在の状態

setState: 現在の状態を更新するための関数

useState: これはReactのメソッド

initialState: 初期値

つまり、useStateを実行すると、現在の状態とそれを更新するための関数が返ってくる。

stateの更新

setState(newState)

setState: 更新関数

newState: 新しい値

setStateをnewStateに書き換える。

propsとstateの違い

props: 親から子のコンポーネントに引き渡す引数のようなもの

state: コンポーネントの中で宣言され、制御される

propsは親から子に渡されるだけで、子から親に対し値を更新することはできない。

stateをpropsに渡す

stateはコンポーネントの中でしか使えないため、

だいたいはpropsに渡して更に子のコンポーネントに渡して使われる。

その際の更新関数は、そのままpropsとして渡さず、関数化する。

const Article = (props) => {
  const [isPublished, setIsPublished] = useState(false)
  const publishArticle = () => {
    setIsPublished(true)
  }
  return (
    <div>
      <Title title={props.title} />
      <Content content={props.content} />
      <PublishButton isPublished={isPublished} onClick={publishArticle} />
    </div>
  );
};

isPublishedを子のコンポーネントの中のPublishButtonコンポーネントで処理する。

更新用関数setIsPublishedは、直接PublishButtonに渡すのでなく、publishArticleと関数化する。

この関数をPublishButtonのonClickというpropsとしてpublishArticleを渡している。

PublishButtonコンポーネントは以下

const PublishButton = (props) => {
  return (
    <button onClick={() => props.onClick()}>
      {props.isPublished.toString()}
    </button>
  )
}

propsとして受け取る

buttonタグでは、propsで渡ってきたonClickという関数がonClickイベントで実行される。

関数の渡し方OK / NG例

OK

<PublishButton isPublished={isPublished} onClick={publishArticle} />
コールバック関数を使う場合
<PublishButton isPublished={isPublished} onClick={() => publishArticle()} />

NG

<PublishButton isPublished={isPublished} onClick={publishArticle()} />

無限レンダリングが起きてしまう例

()を付けることによってpropsとして渡すときに関数を実行することになってしてしまう。

OKの例は関数をpropsとして渡している。

レンダリングをするたびに関数を実行するという無限ループになってしまう。

useStateの実用的な使い方

const TextInput = () => {
  const [name, setName] = useState('')      setNameという更新関数が存在している。
  
  const handleName = (event) => {         setNameに値を渡すためのhandleNameという関数を宣言
    setName(event.target.value)          このhandleNameはeventをパラメータとして受け取る。
  }                           event.target.valueはフォームの入力値
  
  return (
    <input
      onChange={(event) => handleName(event)}  だから、handleNameを使うときは引数の指定が必要。
      type={'text'}                  onChangeイベントが発火したらeventという値をhandleNameという関数に渡す
      value={name}
    />
  );
};

つまり、onChangeベントでeventという値が変わる度に、handleNameがeventに渡され、event.target.valueがsetNameに渡される。

prevStateを活用する

クリックするとカウントアップしていくような機能に使える。

prevStateは、更新前の値を引数としてとってくることができる。

初期値を0として、関数countUpの中でsetCountを呼び出し、更新前の値に+1した値を返すというもの。

const Counter = () => {
  const [count, setCount] = useState(0)

  const countUp = () => {
    setCount(prevState => prevState + 1)
  }

countUp部を省略しないでreturnをつかって書くと、以下のようになる。

const countUp = () => {
  setCount(prevState => {
    return prevState + 1
  })
} 

バグが出るcount機能の書き方

const countUp = () => {
  setCount(count + 1)
}

この書き方の何がいけないのか?

クリック回数分正確にカウントがされない。クリック数とカウント数に差異が生じる。

prevStateは更新前の値を参照して、+1しているため、クリック数とカウント数に差異が生まれるということが無くなる。

ON/OFFを切り替えるボタン

true/falseを切り替えるようにする。

const ToggleButton = () => {
  const [open, setOpen] = useState(false)

  const toggle = () => {
    setOpen(prevState => !prevState)
  }

toggleという関数をつくり、setOpenのprevStateをtrue/falseを反転させて更新をかける。

!を付けることで反転ができる。

toggleというのは切り替えるという意味

useEffectを使う

useEffectとは・・・レンダリングにより引き起こされる処理のこと

実行タイミングの指定方法

毎回実行
useEffect(() => {
  console.log("Current count is...", count)
})

初回レンダリング後のみ
useEffect(() => {
  console.log("Current count is...", count)
}, [])

第二引数に空配列をしていする。

配列の中の値が変更されたときのみ実行されるというもの。

triggerが変更される度
useEffect(() => {
  console.log("Current count is...", count)
}, [trigger])
trigger1かtrigger2が変更される度
useEffect(() => {
  console.log("Current count is...", count)
}, [trigger1, trigger2])

クリーンアップ

クリーンアップとは、コンポーネントの中で外部DBやAPIを購読した場合の、購読の解除をすること。

購読とは、DBの値に変更があった場合などにそれを受け取り、それを基に表示を変えるなどの処理。

なぜ解除をするか?値をとりっぱなしだと意図しない挙動になってしまう。

if (open) {
  console.log('Subscribe database...')
}
return () => {
  console.log('Unsubscribe database!')
}

このreturnをクリーンアップ関数という

useEffectをどう使うか

非同期通信をコンポーネントの中で使う場合は、useEffectの中で使うのがルール

fetch・・・データを取りに行って取得して戻ってくるという意味。getとは違う。

fetch API というものがデフォルトで備わっている。

このfetch APIを使って外部APIにアクセスできる。

このfetchをuseEffectの中で使う。

まとめ

全9回のYouTubeを全て最後まで理解することが出来ました。

“日本一わかりやすい”と命名されているだけあってめちゃめちゃ分かりやすかったです。

実際に手を動かしてアプリの作成はできないので、アプリを作成したくなりました!

それではアプリ制作に入っていこうと思います!!

コメント

タイトルとURLをコピーしました