🥴

Viteで始めるReactチュートリアル副読本

2022/01/17に公開

はじめに

Reactのチュートリアルって難しくないですか?
少なくとも僕の周りではそんな声がたくさん上がりました。

そこで、実際に自分でドキュメントを読み進めた中で、つまずきそうな箇所をピックアップしておこうと思いました。
あくまで基本的な内容はドキュメントを進めながら理解していただく形になるので、ご理解の程お願いします。
https://ja.reactjs.org/docs/getting-started.html

想定する読者

Reactのチュートリアルでつまずいた方

範囲

INSTALLATION ~ MAIN CONCEPTS

INSTALLATION

React公式チュートリアルでは、cdnや create-react-app コマンドが推奨されていますが、
学習目的だけであれば個人的にはVite.jsをお勧めします。
https://vitejs.dev/
理由としては、

  • 環境構築がコマンドラインで完結する
  • HMRで爆速で開発できる
  • PostCSSがビルトインでサポートされている
    といったところですね。

必要な環境

  • Node.js 12以降
///node
npm init vite@latest
///yarn
yarn create vite

こちらのコマンドを実行した場合、対話形式での環境設定が開始されます。
使用するJSフレームワークについて聞かれますので、Reactを選択してください。
オプションでTypeScriptの導入もすることができます。
便利ですね🤗

インストールが完了したらCLIの指示に従ってコマンドを実行してください。
コードについてはsrc/main.jsxsrc/main.tsxに記入していきます。

main.jsx
import { useState } from 'react'
import logo from './logo.svg'
import './App.css'

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

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>Hello Vite + React!</p>
        <p>
          <button type="button" onClick={() => setCount((count) => count + 1)}>
            count is: {count}
          </button>
        </p>
        <p>
          Edit <code>App.tsx</code> and save to test HMR updates.
        </p>
        <p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
          {' | '}
          <a
            className="App-link"
            href="https://vitejs.dev/guide/features.html"
            target="_blank"
            rel="noopener noreferrer"
          >
            Vite Docs
          </a>
        </p>
      </header>
    </div>
  )
}

export default App

簡単にこのファイルの中身を説明すると、
localhostを起動した際に表示されるコードがreturnの中身に記載されています。
基本的にはこれ以降使用することはないので、returnの中身は削除して大丈夫です。


MAIN CONCEPTS

この章では公式ではクラスコンポーネントで記載されている箇所もありますが、基本的には関数コンポーネントで進めるほうがベターです。
理由については下記の記事が詳しいので、興味があれば読んでみてください。
https://tyotto-good.com/blog/reaseons-to-use-function-component

Hello world

このページに記載されているコードはほぼ使用する機会がないです。
Viteを使ってもNext.jsを使ってもこの書き方をすることは皆無に等しいので、こんな書き方もあるんだくらいの認識で大丈夫です。

renderメソッドの中身

ReactDOM.renderメソッドは第一引数に追加する要素、第二引数に第一の要素の親要素になる要素をとります。
つまり例のコードは#rootを取得し、その子要素に<h1>Hello world</h1>を追加するコードとなっています。

JSXの導入

このページでは特筆すべき難しい点はないと思います。
逆にあれば聞きたいのでコメントで教えてください。

要素のレンダー

このページも先ほどと同じく難しい箇所はないかと思われます。

コンポーネントとプロップス

Reactの関数コンポーネントは引数を指定した場合、props(プロパティ)オブジェクトを受け取ります。
一応引数の名前は(当然ですが)hogeだろうがfooだろうが動きます。
ただ、慣習的にpropsという名前で宣言されることが多いので、素直に従ったほうがいいと思います。

Example.jsx
const Example =(props)=>{
 /*
 *props:{
 *  name: 'hoge',
 *  sex: 'men'
 *}
 *このとき、呼び出し元の属性名が子要素のpropsのキーとして使用されます。
 */
  return(
    <h1>Helo {props.name} sex:{props.sex}</h1>
  )
}

const App=()=><Example name="hoge" sex="men"/>

stateとライフサイクル

propsが外部から与えらる値なのに対して、stateはコンポーネントの内部で宣言される値を指します。
すでにVue.jsになじみがあるなら、Vue.jsのoptionsAPIのdataに相当するものというイメージで大丈夫です。

ドキュメントでは関数コンポーネントからクラスコンポーネントへとありますが、
それをさらに関数コンポーネント+ReactHooksに書き直していきましょう。

Clock.jsx
import { useState, useEffect } from 'react'

const Clock =()=>{
  const [date, setDate] = useState( new Date )
  
  useEffect(()=>{
    const timerID = setInterval(()=>setClock( new Date ), 1000)
    return ()=>{
      clearInterval(timerID)
    }
  })
  
  return (
    <time dateTime={ date }>
      { date }
    </time>
  )

}
export default Clock

ドキュメントのコードよりも簡潔な記述になりました🙌
ここで注目していただきたいのは、[date, setDate]という形での変数宣言です。
普段からJavaScriptに慣れていない方は奇妙な書き方に思うかもしれませんが、順を追って理解していきましょう。

結論から言うと、この箇所で使用されているのは分割代入というJavaScriptの文法です。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

const [hoge, huga] = [1, 1000, undefined]

console.log(hoge) /// output 1
console.log(huga) /// output 1000

要するに右辺の配列の要素を、左辺の添字が対応する変数に代入していくということです。
改めて該当箇所のコードを見てみましょう。

const [date, setDate] = useState( new Date )

useState関数を利用した場合、返り値としてstateとそのstateを更新する関数が入った配列が渡されます。
なので、処理の順番を可視化していくと、

const [date, setDate] = useState( new Date )

const [date, setDate] = [ state, setState() ]

const date = state,
      setDate = setState()

と処理されている感じです。
※あくまでイメージまでに認識してください。

分割代入について Tips

先ほどの例では配列でしたが、分割代入はオブジェクトに対しても使用することができます。
オブジェクトに対して使用した場合は、左辺の変数名に対して、対応したオブジェクトのキーの値が代入されます。

Ex.jsx
const Example =(props)=>{
 const { name, age } = props
 
 return(
   <div>
     <h2>{ name }</h2>
     <h3>{ age }</h3>
   </div>
 )
}

const App ()=>{
  <>
    <Example name='hoge' age='20' />
  </>
}

さらに言うと、引数を受け取る時点で分割代入しておいたり、分割代入した値をオブジェクトのキーとは別の名前で使用することもできます

Ex.jsx
const Example1 =()=>{
 const { hoge:name, huga:age } = props
 
 return(
   <div>
     <h2>{ name }</h2>
     <h3>{ age }</h3>
   </div>
 )
}

const Example =({name, age})=>{
  return(
    <div>
     <h2>{ name }</h2>
     <h3>{ age }</h3>
   </div>
  )

}

const App ()=>{
  <>
    <Example1 hoge='hoge' huga='20' />
    <Example2 name='hoge' age='20' />
  </>
}

この場合、コンポーネントExample・Example1・ Example2は同じものが表示されます。
僕はこれが言いたかった
他の方のReactの記事をみると当たり前のように分割代入が使用されています。
そりゃES6以降の主要な機能は理解したうえで読み解いていくことが好ましいのは間違いないですが、みんながみんなその前提で記事を書いてしまうと初学者が躓いてしまう原因になりかねないと思います。
(分からないところがあれば適宜ググるくらいの気概を持てと言われればそれまでですが)

特にReactだとJSX内での変数使用に中括弧、変数宣言に中括弧、引数にも中括弧といたるところで中括弧が使用され、初学者はどういうことだってばよ状態に陥りやすいように感じます。
その点Vueだと変数を表示するときは{{}}(ムスタッシュ構文)で差別化されているので幾分わかりやすいですね

イベント処理

このページはJavaScriptの基礎的な知識があれば問題ないかと思います。
クラスコンポーネントの場合はコールバックにthisを付けるくらいですかね。。。

条件付きレンダー

このページのコードを見たときに、冗長な表現になっていると思いませんか?
これには理由があります。
JSXには式を埋め込むことはできますが、文は埋め込むことができないためです。
そのため、例のコードで記載がある通り、

  • 条件によってコンポーネントを出しわけるコンポーネントを定義する
  • 論理演算子(&&)を使用する
  • 条件演算子(a.k.a 三項演算子)を使用する
    といった手法を使用する必要があります。

リストとキー

配列をもとにコンポーネントを作成して表示する場合はArray.prototype.mapを使用する必要があります。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map
使用例

const arr = [0, 10, 4, 5, 6]
const doubled = arr.map(el=>el * 2)
console.log(doubled) /// output [0, 20, 8, 5, 6]

Array.prototype.mapのコールバックは3つの値(現在の要素:必須,添え字:任意,処理している配列:任意)を受け取り、配列の各要素に処理を加え、実行結果を新しい配列をとして返却します。
配列に繰り返し処理を行うといった点で似たメソッドとして、Array.prototype.forEachもあります。
https://teratail.com/questions/290703
こちらのページのベストアンサーのように書くこともできますが、記述が冗長なうえに公式ドキュメントでもmapメソッドを使用していますので、特別な事情がない限りあえてforEachで書く必要はないです。

stateのリフトアップ

このページもドキュメント通り進めれば対して問題は無いかと思います。
データは上から下へ
を合言葉覚えればそれで十分だと思います。

コンポジション vs 継承

子要素をprops.childrenとして受け取れることについては、いきなり出てきたように思えますが、実際にはかなり前の章で説明されています。
2.JSXの導入のページの下のほうで、propsの下にchildrenが定義されていることが確認できますね。


後書き

今回はReactのドキュメントに焦点を当てて、簡単に解説をしてみました。
ドキュメントを読むだけでもJavaScriptの包括的な知識が求められるので、かなり勉強になりますね💪
次のステップはReactのチュートリアルを進めながらドキュメントで学んだことを再度確認することをお勧めします👼

よきReactライフを

Discussion