見出し画像

【最新版・hooks対応】 Reactの基礎を学んでTODOアプリを作ろう!

==== 追記:  2020.1.28 ===========
最新のReactに準拠した内容に更新しました!
これに伴って1,000円に値上げしました。
===========================

こんにちは!京都のITベンチャーでフロントエンドからバックエンドまで幅広く実装していた@DragonTaro1031です。CyberAgentでの長期インターンでフロントエンドを実装した経験もあります。

大好評のreactのチュートリアルだったのですが、時代に取り残されたものとなっていたのでアップデートすることにしました。

消してもよかったのですが、僕のチュートリアルがどのようなものなのかを知っていただきたいので新しいnoteにして無料公開することにしました!

旧版を読んでみて僕の説明に満足してから購入していただけたらと思います!また、旧Reactを知っておくことで昔の記事を参考にすることができるようになるので、余裕があればやってみることをおすすめします!​

このチュートリアルのゴールは以下のようなアプリが作れるようになることです。

画像1

あくまでアップデートしただけなので、無料版と同じところもたくさんあります。

では、何が違うのか。はい、アップデート版では、旧Reactと最新のReactを対比しながら説明しています。それに伴ってコードの全面改修と新たに4,000字以上の追記を行いました。

それぞれを説明している記事はありますが、新旧の対応がわかりにくいことが多いです。また、そもそも初学者の人には新旧の判断がつかないということもあると思うので、昔のReactもこれからのReactも学べるようにしてみました。

構成

必要に応じて用語解説や理論の解説もしますが、基本的にはイメージでreactの概念を理解して、とにかく書けるようになることを目的としたチュートリアルにしようと思っています。

というのも説明を書いてみたのですが、どうしても専門用語が多くなってしまい理解に時間がかかってしまいます。とにかく動くreactのコードを書いてreactの楽しさを知ってもらうことに重点を置くことにしました。

楽しくなって興味が出たら理論を学んでいただけたらと思います。

0章 reactを勉強する前に
1章 reactとは
2章 環境構築
3章 HelloWorld
4章 カウンターAppで学ぶstate
5章 TODOアプリの雛形を作る
6章 コンポーネントを分割する
7章 削除機能を実装する

このような構成です。これは無料版と同じです。0章~2章に関しては基礎的内容でほぼ変更はありません。


対象

この記事はjavascript(以下js)をある程度勉強した次のステップとなっております。ドットインストールを一通りやっていれば十分です。pragate等でも問題ありません。


0章 reactを勉強する前に

画像3

reactを勉強する前にes6(es2015)というものについて解説します。これは簡単にいうとjsの新機能です。jsでがっつり開発をしている人ならわかると思うのですが、従来のjsってクソなんですよ。

それで散々disられてたんですけど、2015年にアップデートされました。これによってjsはモダンな言語として再度注目を浴びるようになりました。

ほとんどのreactの入門記事ではes6知ってるよね?という前提で話が進んでいます。多くの人が通る本家のreactチュートリアルもes6の解説はほとんどありません。ちなみにreactは従来のjsでも書けるのですがコードが冗長になってしまうので、最近ではほとんどのコードがes6で書かれています。

そこで、reactをやる上で最低限知っておきたいes6の書き方について説明していきます。ここを詳しくやるとそれだけで挫折してしまうので、こんなもんなんだと思って進めてもらったらいいと思います。

僕もそんなに使わない構文だと未だに理解できてないのとか知らない構文もあります。それでも大規模なreactの開発をできているのでご安心いただけたらと思います。

では、実際に見ていきましょう。

letとconst

es6で一番よく使う記法です。jsは本来varによって宣言するのですが、es6では、変数をlet、定数をconstで定義します。

定数を使うことに違和感があるかもしれません。値を変更したいときにどうするんだ?って思うかもしれないですが、そのときは元の値を直接いじらずに新たに宣言した定数に元の値を変更したものを代入するという方法をとります。

let a = 1;      // 変数を宣言     
a += 1;         // aにa+1を代入
console.log(a); // => 2

const b = 1;
// b += 1;      // 定数だからエラー
const c = b + 1 // 新たに定数を宣言して計算結果を代入
console.log(b); // => 1
console.log(c); // => 2

reactではパフォーマンスの向上のために定数を使うんだと思っておけば大丈夫です。これを理解しないと先に進めないというわけではないので、reactができるようになってから、気になる人は勉強してみてください。

また、厳密にはvarとletには違いがありますが、基本的にはletを使うものなんだと思っていてもらったら大丈夫です。(スコープに違いがあります。)

*正確にはconstは再代入を禁止するもので内部の値を書き換えることは可能です。

アロー関数

=と>を使って=>という矢印を用いることからそのように呼ばれています。調べると無名関数云々と書いてありますが、要は定数みたいな感じで関数を宣言できるよってことです。

ちょっと雑になってしまって語弊があるかもしれないですが、reactを書けるようになるにはこれぐらいの理解で十分です。あとで解説しますが、関数型コンポーネントの説明で出てきます。

const HelloWorld = () => {
  return "Hello World!!";
}
// const HelloWorld = () => "Hello World!!";   // 1行でも書ける
console.log(HelloWorld());                       // => Hello World!!

実は従来のjsの関数とは違ってthisの挙動が変わってきます。
"js this"とかでググると色々出てくるのできになる人は調べてみてください!

クラス構文

これは、他の言語と同じです。reactに限っていうと使い方が限定されているので、そこまで理解する必要はないです。extendsによってクラスの継承もできるのですが、初めのうちはextends以下はおまじないだと思っていたらいいでしょう。僕も半年ぐらいおまじないだと思っていました。

class HelloWorld extends React.Component {
 render() {
   return (
     <div>
       HelloWorld
     </div>
   );
 }
}
正確には、React.Componentクラスを継承することで、render関数が使えたりstateやpropsといったreactの構文を使えることができるようになります。
この辺りはオブジェクト指向の基本なので気になる方は調べてみてください。

古き良きReactはクラスベースで書かれていたのですが、hooksが実装された16.8系からは非推奨になりました。代わりに関数コンポーネントで実装していきます。

デフォルト引数

これは結構使うやつで、関数の引数に何も渡されなかったら、このデフォルト引数が引数として用いられます。

const PlusOne = (a = 1) => {   // aのデフォルト値が1という意味
 return a + 1;
}
console.log(PlusOne());        // =>   1 + 1 = 2
console.log(PlusOne(100));     // => 100 + 1 = 101

テンプレート文字列

文字列の中で変数を展開できます。状況に応じてHTMLのclassの名前を変更したいときなどによく用います。shift + @のちょんちょんです。

const Hello = (name) => `${name}, Hello!`, ;
console.log(Hello("Tom"));              // Tom, Hello!

スプレッド演算子

これよく使われてるんですけど、知識がないと意味わからない上に"..."でgoogle検索しても全然違うものがヒットしてしまいます。これだけは、名前と意味を覚えておいた方がいいです。内容としては、配列やオブジェクトを展開できます。

array = [1, 2, 3];
console.log(...array); // 1 2 3

分割代入

これもes6でよく使われる記法です。

const state = {
    hoge: "hoge",
    fuga: "fuga"
}

っていうオブジェクトがあったときに、

const { hoge, fuga } = state

としてやると、それぞれのhoge, fugaに分割して値を代入することができます。reactでは、this.state.hogeみたいな書き方になって冗長なのでこのような書き方が好まれる傾向があります。

const { hoge: Hoge, piyo = "piyo" } = state

console.log(Hoge) // "hoge"
console.log(hoge) // undefined
console.log(piyo) // "piyo"

こんな感じで初期値や名前を変えて代入することもできるのでけっこう便利です。

また、これは配列でも可能で、

const arr = ["hoge", "fuga"];
const [hoge, fuga] = arr;

console.log(hoge) // "hoge"
console.log(fuga) // "fuga"

のように記述できます。これはhooks APIのuseStateで使われています。(後述)

Promiseおよびasync/await

今回のチュートリアルではでてきませんが、jsで非同期処理を実装するときのデファクトスタンダードとなっているAPIです。いずれ使う日が来るのでそんなものがあるということだけ覚えておきましょう。

フロントエンドであればほとんどがfetchでしかPromiseを扱うことはありません。

let user = {};

fetch("/user").then(res => res.json()).then(json => user = json);

# async/await
const res = await fetch("/user")
const user = await res.json()

あくまで上記はイメージですが、このようにしてサーバーとのやりとりを記述することができるようになります。


押さえておきたいes6の構文は以上です。一応一通り目を通してほしいのですが、これだけ見ても実感がわかないと思います。そこでこの章を辞書的に使っていただけたらと思います。これ以降の章でもできるだけこれはes6だから0章みてねってことを書いていきたいと思います。

以下に参考にさせてもらったQiitaの記事を載せておきます。詳しく知りたいかたやよくわからなかった方は以下を参考にしてください。


1章 Reactとは

やっと本題のreactです。reactとはfacebook製のjsのライブラリです。ライブラリとはjsだけではコードをいっぱい書かないといけなくなってしまうので、それを使いやすいように賢い人が頑張って作ってくれたものです。reactはfacebookの賢い人たちが作ったかなり有能なライブラリです。

本家の説明によると、

"Reactはユーザーインターフェースを構築するためのJavaScriptライブラリです。宣言的に書け、効率的に動作し、柔軟性に富んでいます。"

うーん、よくわかりませんね。簡単にいうと、フロントエンドといってユーザーが実際に触る部分(=UI, ユーザーインターフェイス)を開発するときに利用されます。特にリロードを必要としないwebアプリでの利用が広まっています。

web版のTwitterとかわざわざリロードしなくてもツイートを読み込めます。そういったリアルタイム更新的な機能が簡単に作れます。

それぐらいならjQueryでもできそうと思うかもしれません。確かにできるんですが、reactの方がより柔軟に変更できる仕組み(=仮装 DOM)をもっているのと、規模が大きくなってもreactは管理がしやすくなっています。

では、次にreactの重要な用語の解説をしていきます。

コンポーネント

reactそのものと言っても過言ではないのに、なぜか説明がおろそかにされています。直訳すると部品、構成要素です。コードで書くと、以下のようになります。

const HelloWorld = () => {
  return (
    <div>
      HelloWorld
    </div>
  );
}

最新のReactでは関数コンポーネントで全て記述していくので、これがもっとも基本形と言うことができます。

class HelloWorld extends React.Component {
 render() {
  return (
    <div>
      HelloWorld
    </div>
  );
 }
}

従来のReactではこのような実装だったのでかなりシンプルにかけるようになっていることがわかります。

一個のクラスが一個の部品(=コンポーネント)になると理解しておけば大丈夫です。ちなみにクラス以外にも関数もコンポーネントを作ることができます。

そして、コンポーネントという名前の通りこれらは部品にすぎず、組み合わせたり入れごにすることでアプリケーションにを構成していきます。

たとえば、TODOアプリを作るとしたら、全体を包むApp Component、TODOを登録するAddTodo Component、登録したTODOを並べるTodoContainer Component、TODOの内容を表示させるTodoElement Componentを上の図のように組み合わせて作ります。

画像4

なぜこのようにコンポーネントを分けるのか基準は今はわからなくて大丈夫で、コンポーネントのイメージができればOKです。

props

これは親コンポーネントから渡ってきた情報を参照するときに使います。なぜこのような仕組みが必要かというと、コンポーネント内の情報は基本的に他のコンポーネントから参照できないからです。

これを他のコンポーネントに渡す仕組みがpropsです。propsを指定してやることで、子コンポーネントに情報を渡すことができます。µ

また、親コンポーネントからpropsで渡ってきた関数を実行することで親コンポーネントに情報を提供することができます。

例えば、TODOアプリではAppでTODOの情報を管理して、その情報をTodoContainer → TodoElement と伝えることで個々のTODOの情報を表示します。この辺りは実装しないと実感が掴めないと思います。

データをバケツリレーしていくイメージです。上の図では矢印がpropsとして受け渡されるデータを表しています。

画像5

state

stateは各コンポーネント内でのみ管理することができる情報のことをさします。管理とは、何かイベント(例えばユーザーがそのコンポーネントをクリックした)が起きたときに更新することができる、ということです。

この情報を表示している部分がUI(画面)です。reactではこの情報を簡単にHTMLにできます。stateが変更されるとそれがすぐにUIに反映されます。

TODOでは、AppでTODOに関する情報を管理してTODOが追加されるというイベントに対してstateの更新をする実装が望ましいでしょう。そしてTODOが追加さると、そのTODOがすぐにUIに表示されます。

画像6

〜1章のまとめ〜
props: 他のコンポーネントに情報を渡す仕組み
state: 各コンポーネント内でのみ管理できるデータ


2章 環境構築

reactには、最新のjsで書くといいましたが、実はこれ対応していないブラウザがあるんですよね。全く画面が表示されないなんてこともあり得るので、対応させる必要があります。その際にwebpackというトランスパイラを使ってトランスパイルします。

???

もうわけわからない、、って人もいると思います。ここでトランスパイルの説明をしてもいいんですが、もう嫌ってなっちゃう人もいると思うので、ここでは具体的にどうしたらいいのかの説明だけに留めます。

まず、ブラウザ上で実行できるサービスがあるのでとりあえず始めたい!って人はこちらを使っていただけたらと思います。

準備しておいたので、forkしてから使っていただくようにお願いします
他にもjsfiledというサービスでもかけるみたいですね。

まずは、ブラウザ上での実行をしてみるといいと思います。ここで、雰囲気を掴んでからでも環境構築は遅くありません。


自分で環境構築してみたい!という人に向けても簡単に解説していきます。公式のインストーラーを使うように書いていたのですが、あまり良くないので変更しました。

まずはNode.jsをインストールします。インストールにはbrewというMacのパッケージマネージャーを使います。コマンドライン版のAppStoreみたいなイメージです。

ここのサイトに詳しいことは書いてるのですが、要は

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

を実行すればおkです。次にNode.jsをインストールします。

$ brew install node

これでインストールされてnodeコマンドおよびnpmコマンドが使えるようになります。(npmはNode.jsのパッケージマネージャーです。)

次に、create-react-appというものをダウンロードします。これは、コマンド一つでreactの環境構築ができてしまうという優れものです。

$ npx create-react-app myapp

とすることで実行できます。最後のmyappは自分で好きなappの名前をつけることができます。このときに必要なライブラリをインストールするので少し時間がかかります。

ちなみにnpxをつけると自分のPCにない場合はダウンロードして1回だけ使うことができます。また、pathが通っていなくても直下のnode_modulesから探してくれます。探索順としてはpathが通ったグローバルのコマンド、ローカルのnode_modules、そしてどこにもないならダウンロードです。

そして、

$ cd myapp
$ npm start

と、することで開発用のサーバーが立ち上がり、http://localhost:3000に最初の画面が開いてることが確認できると思います。

これで、開発する準備ができたので次から実際にコードを書いていきましょう!

さらにカスタマイズしたい方はwebpackやbabelのインストールから自分でやってみてください。

僕が構築したものをQiitaに投稿してあるのでそちらも参考にしてみてください。

〜2章のまとめ〜
環境構築は少しややこしいので、まずはブラウザ上で実行できるサービスを使ってみて、reactになれる。

次のステップとして、自分で環境を作ってトランスパイルしてみる


3章 HelloWorld

この章では、HelloWorldと表示させるだけのコンポーネントを作成しましょう。まずは、コンポーネントは何で実装できるか覚えていますか?そうですね、jsの関数でしたね。

const HelloWorld = () => {
  return (
    <div>
      HelloWorld
    </div>
  );
}

これがコンポーネントの最小単位です。コンポーネントは必ず一つのjsxを返さなければいけません。jsxは、HTMLの要素 + reactのコンポーネントと思っていただければ十分です。

返すjsxは0でも2個以上でもだめです。

return (
  <div>
    HelloWorld
  </div>
  <div>
    HelloWorld
  </div>
);

このようにしてしまうと、エラーが出て何も表示されないはずです。一度やってみてエラーを確認してみてください。このエラーは自分で開発するときに度々みることになるでしょう。僕はそのエラーを見た瞬間に全てをさとります。

そして、このrender関数の返り値が実際にHTML(正確には仮想DOM)として画面上に表示(render・描画)されます。

このコンポーネントの場合は 、

<div>
   HelloWorld
</div>

が、HTMLとして作られ、画面にHelloWorldが表示されることになります。

// クラスベース
class HelloWorld extends React.Component {
 render() {
   return <div>HelloWorld</div>;
 }
}

クラスベースではこのようになります。関数ベースの方がなんとなくスッキリしていますよね!こんな感じで随時、新旧の比較を記載していきます。

では、これはどこに表示されるのでしょうか。それを指定してやるために、

ReactDOM.render(
  <HelloWorld />,                       // HelloWorldコンポーネントを
  document.getElementById('root')       // id='root'の要素にrenderする
);

と記述します。これの意味は、ReactDOMというReactとは別のライブラリのrender関数に、表示させたいコンポーネントと、表示させたい場所を指定してやります。

例で用いたReactDOM.renderでは、HelloWorldコンポーネントを
画面に表示されている<div id='root'></div>内にrenderするという意味です。

〜3章のまとめ〜
・jsx = HTMLの要素 + reactのコンポーネント
・コンポーネントは必ず一つだけjsxを返す
・ReactDOM.renderを使ってHTMLに表示させる


4章 カウンターAppで学ぶstate

この続きをみるには

この続き: 18,582文字 / 画像5枚

【最新版・hooks対応】 Reactの基礎を学んでTODOアプリを作ろう!

宮川 竜太朗

1,000円

この記事が気に入ったら、サポートをしてみませんか?気軽にクリエイターを支援できます。

これでなんとか明日もあったかいご飯が食べれそう、、ありがとうございます
54
京大の化学工学を専攻しつつITベンチャーでエンジニア(主にrails, react)をやっています。最近ブログも始めたのでよかったらみてください!👉https://dragon-taro.com/profile/
コメント (1)
すごくわかりやすかったです!

1点、6章の3つ目のコードブロック内
<TodoElement key={index} content={todo} />
ではなく
<TodoElement key={i} content={todo} />
が正しいと思います。
コメントを投稿するには、 ログイン または 会員登録 をする必要があります。