##始めに
UIを作成する際は、ずっとjQuery(たまーにRiot.js)にお世話になっていましたが、2020年にもなったし、そろそろ重い腰をあげて、本格的にReactを勉強したい、という事で勉強を始めています。(自分はjQueryも好きですし、現在進行形でお世話になってます)
年始(2020年)に掲げたゴールの一つがReactの習得なので、個人的なアウトプットとして、いくつかメモとして、文章を残していこうと思います。それと同時に、自分と同様、現場で導入されそうだし、そろそろReact勉強したい!という人に向けて書いていこうかなと思います。
※随時、セクションを追加更新していく予定です。
本記事はReactを構成する概念や記法について、ざっくり整理しながら触れます。
(詳細は***Reactのドキュメント***を見まっしょ!)
##Reactとは
UIを構築するための、宣言型JSライブラリです。
jQueryで、少し複雑なUI(例えば、状態を持つような)を作ろうとすると、コードが冗長になりやすかったり、後で見返したときに、「え...何してるのかよく分からん...」となったりということは、jQueryで頑張ってきたエンジニア、Webデザイナーなら、一度は経験があるはずです。
Reactは状態を持つようなインタラクティブなUIの作成をやりやすくしてくれるライブラリとして、設計されています。
導入すると何が嬉しいかというと、コンポーネント単位での実装が容易なので、再利用性が高く、保守性も担保した運用がしやすくなります。
ここら辺、***Atomic Design***の考え方とも親和性が高そう。
(後でこちらも記事としてまとめたい)
ちょっと前まで英語のドキュメントを読むしかなかったですが、今は日本語のドキュメントもVue.js並に充実してる印象です。手始めにチュートリアルを一通りやってみるのが、取っ掛かりとして、一番早いかも。(何事も自分で手を動かす方が理解が深まりますよね?)
Reactの導入
##Reactを構成する記法① JSX
ReactでHTML(DOM)を出力するための独自構文で、JSの機能を備えています。また、埋め込まれた値をレンダリングする前に、エスケープしてくれるので、インジェクション攻撃を防ぐ事ができます。
Reactは、JSXでの記述を強制してる訳ではないですが、JSXで書いた方が圧倒的に楽です。よっぽどこだわりのある偏屈な人じゃなければ、JSX使っていきましょう!最初は違和感あるかもしれないけれど、ここら辺は慣れの問題かなと思います。普段、HTMLやJS書いてるような人ならすぐに慣れると思います。
import React from 'react';
const title = <h1>Study React!!!</h1>
const greeting = <h2 className='greeting'>Hello.</h2>
####JSXでない記法を参考までに
JSX = シンタックスシュガーである事が分かりますね。
import React from 'react';
const title = React.createElement('h1', null, 'Study React!!!')
const greeting = React.createElement('h2', {className: 'greeting'}, 'Hello.')
####JSXは子要素も定義できます
const elem = (
<>
<section className='head'>
<h1>Study React!</h1>
<h2>Hello.</h2>
</section>
<section className='body'>
<h1>
Roadmap
</h1>
</section>
</>
)
####JSXに値を埋め込むことも可能
ただタグを表示するだけでなく、JSの値を埋め込むこともできます。
{ 変数や値 }
let title = 'Study React!';
let greeting = 'Hello';
const heading_s = { color: 'red', borderBottom: '1px solid #DDD' }
let elem = (
<>
//属性の値にも利用できることに注目
<h1 style={ heading_s }>{ title }</h1>
<h2>{ greeting }</h2>
</>
)
####JSXを書く上での注意点
Reactを勉強したての頃、JSXでエレメントを定義する際、以下のように書いてしまってエラーになるケースがあります。(上記の違いは <></>
で囲っていない点)これ、何がいけないかというと、renderメソッドで、描画できるのは、一つのエレメントだけというルールがあるからです。
JSXに子要素をもったDOMを代入する際は、親として、必ず <div>タグ
もしくは、<>タグ(=<React.Fragment>タグ)
で囲ってあげましょう。
(VSCodeやInteliJとか使ってれば、そもそも記法の間違いは教えてくれますが)
const elem = (
<section className='head'>
<h1>Study React!</h1>
<h2>Hello.</h2>
</section>
<section className='body'>
<h1>
Roadmap
</h1>
</section>
)
##Reactを構成する記法② Component
JSXでエレメントを定義し、ReactDOM.render
で描画するだけだと、全く便利さは感じないと思ったはずです(自分もそうでした)。
Reactの真価はコンポーネントを組み合わせてUIを構築していくことにあります。
コンポーネントとは、画面に表示する部品で、表示の内容や必要なデータ、処理などを一つのオブジェクトにまとめます。
ボタンや入力フォーム、カードなど、Webアプリは沢山の小さなコンポーネントとその組み合わせで構築されています。
コンポーネントを作成することによって、再利用可能で、堅牢な仕組みが構築しやすくなります。
デザイナーやフロント寄りの開発をされてる方にとっては、デザインシステムという言葉は見聞きした事があると思います。有名どころだと***GoogleのMaterial Designや、Mailchimpのデザインシステム、SalesforceのLightning Design System等がありますが、世の中には沢山のデザインシステムが存在します。
(デザインシステムのギャラリーサイト***もあって、眺めてるだけでも面白いですよ)
なんでも良いのですが、試しに上記3リンクを開いてみてください。どのサイトにもComponent
が定義されているはずです。各企業は、ブランディングやユーザビリティ、開発効率性の観点から、デザインシステムを設計し、UIをコンポーネントとして定義することによって、一貫性、保守性を保とうと努力しています。
Reactは、そのような要求にも耐えうる開発を進めていくための一つの選択肢とされています。
コンポーネントの書き方にはClass Component(クラスコンポーネント)
とFunctional Component(関数コンポーネント)
の2種があります。参考までに書き方の例を示します。
import React, { Component } from 'react';
//関数コンポーネント
function StudyReact(props) {
return <h1>During study...</h1>
}
//クラスコンポーネント
class StudyReact extends Component {
constructor(props) {
super(props);
this.state = {
status: 'During study...'
}
}
render() {
return <h1>{this.state.status}</h1>
}
}
####コンポーネントでデータを管理するための方法
コンポーネントでデータを扱う主要な手法として、props
と state
という二つのオブジェクトを利用します。この二つの理解は、今後、Reactを勉強していく上で、重要です。
両者の違いは以下の通りです。
-
Props : 親コンポーネントから渡されたプロパティ。
- 値を指定するタイミングは、コンポーネントを作成する時
- 値の変更不可 -
State : そのコンポーネントが持っている状態
- 値を指定するタイミングはコンポーネント作成後
- 値の変更可
上記のルールを踏まえて、コンポーネントを使用する際に意識する事は、親から初期状態として、propsを渡し、stateでそのコンポーネント自身の状態を管理するという点です。
まず、propsの使い方から見ていきます。
値の変更は不可という事は、propsは読み取り専用という事ですね。
以下の実装で名前のプロパティと、担当楽器のプロパティを定義しています。
コンポーネントに定義されたプロパティは、そのコンポーネントが作成された瞬間、後から変更を加える事が出来ません。
propsは、そのコンポーネントがずっと保持し続ける、そのコンポーネントたらしめる要素になります。
(人の名前は名付けられた瞬間、基本的に変える事は出来ませんよね? そういう事です。)
以下では、ビートルズのメンバーを作成しています。
class BandMember extends Component {
constructor(props) {
super(props);
//初期化時に、引数のpropsからnameとpartという値を取り出し、プロパティに設定
this.name = props.name;
this.part = props.part;
}
render() {
return(
<>
<p>
My name is {this.name}. My part is {this.part}.
</p>
</>
)
}
}
class App extends Component {
render() {
return(
<>
{/*各コンポーネントに値を設定*/}
<BandMember name='Paul' part='Base'/>
<BandMember name='John' part='Guitar'/>
<BandMember name='George' part='Guitar'/>
<BandMember name='Ringo' part='Drums'/>
</>
)
}
}
続いて、stateを見ていきます。
上記、実装を利用しながら、stateを説明してみます。
今、バンドメンバーとして、4名が定義されています。
- Paul: Vocal/Bass
- John: Vocal/Guitar
- George: Guitar/Vocal
- Ringo: Drums/Vocal
4人で曲を練習していたある日、Paulが急に「ギターやりたい」と言いだしました。
Georgeは仕方なく、パートをベースに変えざるを得ない状況に立たされてしまいました。
この状況では、最初に、propsで定義していたpart(担当楽器)を変える必要が出てきました。(=コンポーネントの状態を変える) = すなわち状態を持つ必要に迫られました。
こういった要件では、state
を使いましょう。
初期化時のstateの設定は、あくまでもstateの初期化処理にすぎません。
イベントを受け取って、更新する際は、setStateを利用する必要があります。
引数には、初期化時に定義したstateのうち、変更したいオブジェクトを指定します。
this.setState({ ... })
this.setState((state) => ({ ... }))
以下に実装例を示します。
ボタンをクリックすると担当楽器が変わるようになります。
class BandMember extends Component {
constructor(props) {
super(props);
this.name = props.name;
this.part = props.part;
//初期化時にstateを定義しておく
this.state = {
myState: props.part,
}
}
//担当楽器を変えるメソッド
changeBase = () => {
this.setState({myState: 'Bass'})
}
//担当楽器を変えるメソッド
changeGuitar = () => {
this.setState({myState: 'Guitar'})
}
render() {
return(
<>
<p>
My name is {this.name}. My part is {this.state.myState}.
</p>
//各コンポーネント(メンバー)に楽器を変更するボタンを追加
<button onClick={ this.changeBase }>ChangeBase</button>
<button onClick={ this.changeGuitar }>ChangeGuitar</button>
</>
)
}
}
class App extends Component {
render() {
return(
<>
{/*コンポーネント作成時に、各コンポーネントに値を設定*/}
<BandMember name='Paul' part='Base'/>
<BandMember name='John' part='Guitar'/>
<BandMember name='George' part='Guitar'/>
<BandMember name='Ringo' part='Drums'/>
</>
)
}
}
####stateを扱う時に注意するべき点
慣れないうちは、stateで値を更新する時に以下のように、書いてしまいがちですが、この書き方は間違いです。this.stateに値を直接入れられるのは、初期化時(constructor)のみです。
//this.stateに直接代入して、値を変更することはできない
this.state.part = 'Guitar';
//必ずsetStateで値の更新を行う
this.setState({part: 'Guitar'})
***React Hooks***が導入されて、クラスコンポーネントの力を借りずとも、関数コンポーネントでも状態を管理することが出来たので、両者の使い分けは、現場ごとの選択になるのかなと思ってるのですが、そこら辺はもう少し突っ込んで、追ってアウトプットしたいと思います。
##React初学者の所感
- 静的なページならjQueryでも全然良いと思う。
- アプリライクな動的ページを作るならReactやReactでUIを作る考え方は、いいかげんキャッチアップしといた方が良さそう。
- 逆にいうと、LPなどを作るようなWebデザイナーさんは、無理して勉強しなくても良いと思う。JSの流行り廃りは激しいし。興味があれば、仮想DOMの概念やコンポーネント化してUIを設計する手法とかは勉強してみると視野が広がるし、面白いと思うし、今後の仕事に活かせるかも。