Reactのキャッチアップが必要になったので公式 を一通り読んだことをまとめました。
自分用のメモなので間違い、分かりにくいところがたくさんあると思います。
Reactを触る上での最低限のポイント。
let
、const
で変数を定義する(var
と等価)
- クラスメソッドの定義の間にカンマは不要
class MyClass {
method1() {
// メソッドの定義
}
//ここのカンマが不要
method2() {
// メソッドの定義
}
}
メソッド内のthis
の値に注意
- オブジェクト指向の言語ではメソッド内の
this
はそのメソッドが属するオブジェクト自体を指すこと
- JavaScriptではメソッドの呼び出し方によって
this
の値が変わることがある
アロー関数
function
よりも短く書ける
x => x * 2
はfunction(x) { return x * 2; }
と同じ
- 関数内の
this
を持たない
this
は外部メソッドの値を保持する
const obj = {
name: 'John',
regularFunction: function() {
console.log(this.name);
},
arrowFunction: () => {
console.log(this.name);
}
};
obj.regularFunction(); // 出力: John
obj.arrowFunction(); // 出力: undefined
JSXの導入
JSXについて。
// 丸括弧で囲む
return (
<div>
<h1>Hello, World!</h1>
<p>Welcome to React.</p>
</div>
);
- コンパイル後はJavaScriptオブジェクトに変換される
- if文の条件式、引数などに使える式である
- 文字列リテラルは
""
、''
で加工
- HTMLの属性名はキャメルケース
- HTMLタグの要素が空の場合は
/>
で閉じれる
- 描画前に値はエスケープされる(XSS対策済み)
- Babelでコンパイルされる
- JSXをコンパイルしたものをReact要素と呼ぶ
- React要素を元にDOMを描画する
要素のレンダー
描画に関するDOM関連の基礎知識。
React特有のコンポーネント、propsについて。
//関数コンポーネント
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
//クラスコンポーネント
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
stateとライフサイクル
状態管理に関する基礎知識。
イベント処理
状態を変更する際のイベント処理について。
Reactのイベント処理
- DOM要素のイベント処理と似ている
- イベント名はキャメルケース
- JSXのイベントハンドラは文字列ではなく関数を渡す
- クリックイベントでfalseを返すには
preventDefault
を呼び出す
this
の値はメソッドがどのオブジェクトに属しているかによって変化する
- メソッド内での
this
は当メソッドが所属しているオブジェクトを参照する
- JSX内の
this
の扱いには注意する
- 参照するオブジェクトを明示的に
bind
する必要がある
bind
とはthis
が参照するオブジェトを指定するための処理
コールバック関数をアロー関数で定義することでthis
が正しく参照される
- アロー関数の記述を見つけたら
this
の参照先に注意する
onClick
で呼び出すコールバックメソッドのthis
の扱いに注意
bind
でthis
の参照先を指定する
- アロー関数を使い
this
の参照先を明示する
Reactではクリックイベントが発生すると自動でイベントオブジェクトが自動生成される
- イベントオブジェクトには次のようなものが含まれている
target
: イベントが発生した要素
type
: イベントの種類
currentTarget
: イベントハンドラがバインドされている要素
- イベントオブジェクトでユーザーの操作に関する情報を取得できる
条件付きレンダー
render
関連。
render
から処理を追い始めるのが良い
render
、coustructor
、イベントハンドラに注目して読むと処理の大まかな流れを読める
JSX内で{}
を使うと演算子、式を含めることができる
JavaScriptでの‘condition ? true : false
はRubyの三項演算子と同じ
コンポーネントの再描画のトリガー
render
がnull
を返してもコンポーネントのライフサイクルは影響されない
- 表示自体は非表示になる
- ライフサイクルメソッドは実行される
ライフサイクル
ライフサイクルメソッドは必ず関連して動作している訳ではない
リストとkey
リストの描画時の注意点。
- 要素のリスト項目の作成時には各要素にユニークなキー属性を付ける必要がある
- 再描画時にリスト要素の一位正を追跡できないため要素の順番を正確に反映できない
- パフォーマンスの低下
//要素のリスト項目にキーが無い
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}
//要素のリスト項目にキーを追加
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
- 要素のリスト項目のキー要素はユニークな文字列が良い
- リスト形式の子コンポーネントを呼び出す場合は親コンポーネント側でユニークなキーを指定して呼び出す
function ParentComponent() {
const items = ['item1', 'item2', 'item3'];
const listItems = items.map((item, index) => (
<ChildComponent key={item} item={item} />
));
return <ul>{listItems}</ul>;
}
function ChildComponent({ item }) {
return <li>{item}</li>;
}
- リスト出力時の
map()
を{}
を使ってインラインで埋め込むこともできる
フォーム
フォーム描画時のポイント。
Reactは変更される状態はコンポーネントのstate
に保持される
state
はsetState()
メソッドでのみ更新できる
ユーザーが入力した内容、イベントをstate
に反映することでコンポーネントを制御する
- ユーザーの入力をトグルにして動的に色々な処理ができる
- Rails + Reactで実装するメリット
preventDefault()
は、通常のブラウザの挙動をキャンセルし、ページ遷移やリロードを防止する
- ユーザーの入力に対して独自の処理を追加する時に使用する
フォーム内のinput
タグのvalue属正をstate
と同期させることでユーザーの入力をリアルタイムにReact側に送信できる
- ユーザーの入力がリアルタイムに
state
に反映される
フォームないのtextarea
タグもinput
と同様にvalue属性をstate
と同期させることでリアルタイムにReact側に送信できる
select
タグのvalue属性に配列を渡すことでオプションを複数表示することができる
[]
を使うことでstateの持つプロパティを動的に変得ることができる(jsのComputed Property Names)
- Rubyのハッシュも同じようなことができる
- Rubyはキーがシンボルが主流、jsは文字列が主流
this.setState({
[name]: value
});
- フォームに入力させたくない場合はvalue属性にundefinedかnullに設定すれば良い
- フォームに一度入力した後に変更不可にする場合は
disabled
属性をstate
を使って動的に変更することで実現できる
state のリフトアップ
state
を共通親に設定するリフトアップについて。
- 複数のコンポーネントの
state
を共通化したい場合は共通の親コンポーネントにstate
を移動する(stateのリフトアップ)
state
のリフトアップの影響
- 同じような記述(ボイラープレート)がたくさん生まれる
- バグを発見しやすい
- 子コンポーネントの
state
が共通化される
state
から計算できる値はstate
として保持しない
- データの一貫性が保たれる
- データフローが明確になる
- デバッグ時にデータが追いやすい
props
を子要素で呼び出す時のポイント。
props.children
は呼び出し側の子要素を子コンポーネント内で表示できる特別なプロパティ
function Sidebar(props) {
return (
<div className="sidebar">
<h2>{props.title}</h2>
<p>{props.description}</p>
<div>{props.children}</div>
</div>
);
}
function App() {
return (
<Sidebar title="Sidebar Heading" description="This is the sidebar content.">
<button>Click me</button> // props.childrenで呼び出される
<p>Additional content</p> // props.childrenで呼ばれる
</Sidebar>
);
}
Reactの流儀
描画処理を追加するまでの手順。
UIを作る手順
1. JSONのデータ構造を分割して、それぞれの部分をどのReactコンポーネントとしてUIに表示するか決める(図を書いた方が分かりそう)
- 表示部分を四角く囲んで名前を付ける
- 出来上がった図をリスト形式でネストさせて構造を把握する
2. データモデルを受け取りUIの描画だけを行う(ユーザーからの操作は不可)
- 表示とユーザー操作を切り離す
- この段階では
props
だけ使い、state
は使わない
- 大きい枠組みから作り始めた方が楽
3. 何をstateにするか決める
- 必要になった時に
state
を元に処理を追加することを意識(不要なstateを作らない)
- 何をstateにするか決める
- 親コンポーネントからの
props
であればstate
ではない
- 時間経過で変化しないなら
state
ではない
- コンポーネント内の
props
、state
から算出できるならstate
ではない
4. stateをどのクラスに配置するか決める
- stateで表示する全てのコンポーネントを洗い出す
- 見つけたコンポーネントの共通の親コンポーネントを見つける
- 共通の親コンポーネント or そのさらに親コンポーネント がstateを持つべきか決める
- stateを持つべきコンポーネントが見つからなかったらstate保持だけのコンポーネントを作る
感想
React難しい...
今まで学習してきたなかで間違い無く一番難易度が高いと感じてます。
ただ、これを乗り越えれば苦手だったフロントエンドとも仲良くなれそうなので地道にやっていきます!
参照
Hello World – React