| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

差分

ナビゲーションに移動 検索に移動
2,404 バイト追加 、 2021年10月11日 (月) 12:21
==[[React]]==[[Node.js]] |
{{amazon|4873117887}}
#[http://typea.info/blg/glob/2017/08/react-react-router-redux-saga.html React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用する]
#[http://typea.info/blg/glob/2017/08/react-react-router-redux-saga-ajax.html React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用したものからAjax通信を組み込む]
#[http://typea.info/blg/glob/2017/08/react-react-router-redux-saga-superagent-bootstrap.html React環境->>React Router->>Redux-Saga->>SuperAgent に Bootstrapを適用する]
==導入==
*https://facebook.github.io/react/docs/installation.html
*https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README[[R]]EADME.md#table-of-contents*ReactのSPAを作成するのによい方法[[React]]のSPAを作成するのによい方法 [[npm ]] install -g create-react-app*Reactはバックエンドロジックやデータベースを持たないが、使いたいものを使えばよい。https://ja.reactjs.org/docs/create-a-new-react-app.html<pre>npx create-react-app my-appcd my-appnpm start</pre>*[[React]]はバックエンドロジックやデータベースを持たないが、使いたいものを使えばよい。
*Babelやwebpackのようなビルドツールも設定なしに利用できる。
PS C:\workspaces\vscode\reactlesson> &gt; create-react-app react-lesson Creating a new [[React ]] app in C:\workspaces\vscode\reactlesson\react-lesson.
Installing packages. This might take a couple minutes.
:
*アプリケーションが作成されたら実行
PS C:\workspaces\vscode\reactlesson> &gt; cd react-lesson PS C:\workspaces\vscode\reactlesson> &gt; [[npm ]] start
*実行された
[[File:1086_react01.jpg]]
*/src/App.js を書き換えてみる
import [[React]], { Component } from 'react';
import logo from './logo.svg';
import './App.css';
const element = (<&lt;h1>&gt;Hello,world<&lt;/h1>&gt;);
class App extends Component {
render() {
[[File:1087_react02.jpg]]
*リリース準備ができたら、以下を実行することで、buildフォルダ以下に最適化されたアプリケーションを作成する
[[npm ]] run build 
==クイックスタート==
===JSX===
const element = <&lt;h1>&gt;Hello,world!<&lt;/h1>&gt;;*文字列でも、HTMLでもなく、JSX文字列でも、[[HTML]]でもなく、JSX*JavaScriptの拡張文法[[JavaScript]]の拡張文法*テンプレートと思われるかもしれないが、完全なJavaScriptテンプレートと思われるかもしれないが、完全な[[JavaScript]]*JSXはReactの要素を生成するJSXは[[React]]の要素を生成する
===JSX表現===
*どのようなJavaScriptの表現も、中括弧で囲むことでJSXに埋め込むことができるどのような[[JavaScript]]の表現も、中括弧で囲むことでJSXに埋め込むことができる*const element = (<&lt;h1>&gt;Hello, {formatName(user)}!<&lt;/h1>&gt;);
<&lt;!DOCTYPE html>&gt; <&lt;html>&gt; <&lt;head>&gt; <&lt;meta charset="UTF-8" />&gt; <&lt;title>&gt;Hello World<&lt;/title>&gt; <&lt;script src="https://unpkg.com/react@latest/dist/react.js"><&gt;&lt;/script>&gt; <&lt;script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"><&gt;&lt;/script>&gt; <&lt;script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"><&gt;&lt;/script>&gt; <&lt;/head>&gt; <&lt;body>&gt; <&lt;div id="root"><&gt;&lt;/div>&gt; <&lt;script type="text/babel">&gt;
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {firstName:'Hiroto', lastName:'Yagi'};
const element = (<&lt;h1>&gt;Hello, {formatName(user)}!<&lt;/h1>&gt;); ReactDOM[[React]]DOM.render(
element,
document.getElementById('root')
);
<&lt;/script>&gt; <&lt;/body>&gt; <&lt;/html>&gt;
*コンパイルされたJSXは通常のJavaScriptオブジェクトコンパイルされたJSXは通常の[[JavaScript]]オブジェクト
*JSXをif文やforループ、変数への割り当て、引数や戻り値に利用できる
function greeting(user) {
var now = new Date();
if (5 <&lt;= now.getHours() && now.getHours() <&lt;= 12) { return <&lt;h1> &gt; Good morning {user.firstName + ' ' + user.lastName}.<&lt;/h1>&gt;;
} else {
return <&lt;h1> &gt; Hello {user.firstName + ' ' + user.lastName}.<&lt;/h1>&gt;;
}
}
====属性に利用====
*中括弧を利用して、二重引用符なし(使用すると文字列リテラルとして扱われる)で直接利用できる。
<&lt;div id="root"><&gt;&lt;/div>&gt; <&lt;script type="text/babel">&gt;
function greeting(user) {
var now = new Date();
if (5 <&lt;= now.getHours() && now.getHours() <&lt;= 12) { return <&lt;h1> &gt; Good morning <&lt;a href={user.webpageUrl}>&gt;{user.firstName + ' ' + user.lastName}<&lt;/a>&gt;.<&lt;/h1>&gt;;
} else {
return <&lt;h1> &gt; Hello <&lt;a href={user.webpageUrl}>&gt;{user.firstName + ' ' + user.lastName}<&lt;/a>&gt;.<&lt;/h1>&gt;;
}
}
const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};
const element = (<&lt;h1>&gt;{greeting(user)}<&lt;/h1>&gt;); ReactDOM[[React]]DOM.render(
element,
document.getElementById('root')
[[File:1089_react04.jpg]]
====子要素====
*子要素がない場合、XML同様 子要素がない場合、[[XML]]同様 /> &gt; で閉じる
*子要素を含む
*JSXはHTMLよりJavaScriptにより近い。ReactDOMはキャメルケースプロパティJSXはHTMLより[[JavaScript]]により近い。ReactDOMはキャメルケースプロパティ(HTMLでは、class がclassName、HTMLではtabindexがtabIndexなど)を持つ
function greeting(user) {
return <&lt;div>&gt; <&lt;h1> &gt; Good morning {user.firstName + ' ' + user.lastName}.<&lt;/h1>&gt; <&lt;h2><&gt;&lt;a href={user.webpageUrl}>&gt;webpage<&lt;/a><&gt;&lt;/h2>&gt; <&lt;/div>&gt;
;
}
const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};
const element = (greeting(user));
ReactDOM[[React]]DOM.render(
element,
document.getElementById('root')
);
[[File:1090_react05.jpg]]
====インジェクション攻撃の予防インジェクション[[攻撃]]の予防====*デフォルトでReact デフォルトで[[React]] DOMは、JSXに埋め込まれた値をレンダリング前にエスケープする
*明示的にアプリケーションに記述しなくてもインジェクションされないことを保証する
*XSS攻撃の予防を助けるXSS[[攻撃]]の予防を助ける
function greeting(user, title) {
return <&lt;div>&gt; <&lt;h1>&gt;{title}<&lt;/h1>&gt; <&lt;h2> &gt; Good morning {user.firstName + ' ' + user.lastName}.<&lt;/h2>&gt; <&lt;h2><&gt;&lt;a href={user.webpageUrl}>&gt;webpage<&lt;/a><&gt;&lt;/h2>&gt; <&lt;/div>&gt;
;
}
const title = "<&lt;input type='button'>&gt;";
const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};
const element = (greeting(user,title));
ReactDOM[[React]]DOM.render(
element,
document.getElementById('root')
);
[[File:1091_react06.jpg]]
====JSX Represent [[R]]epresent オブジェクト====*Babelは、ReactBabelは、[[React]].createElement()を呼び出しコンパイルを行う
*以下の2つは同じ意味
const element1 = (<&lt;h1 className='greeting'>&gt;hello<&lt;/h1>&gt;); const element2 = [[React]].createElement('h1',{className:'greeting'},'hello');*[[React]].createElement()は、バグを防ぐ手助けをするが、本質的には以下のようなオブジェクトを生成する
// 簡易表現
const element = {type:'h1',props:{className:'greeting',children:'hello'}};
*これらの要素を"[[React ]] elements"と呼ぶ
*画面に表示させたいものの記述と考えることができる
*Reactはこれらのオブジェクトを読み、DOMの構築と最新化に利用する [[React]]はこれらのオブジェクトを読み、DOMの構築と最新化に利用する
===Elementsのレンダリング===
*Elements はReact は[[React]] アプリケーションの最小のビルディングブロック
*1つの要素は、画面上に表示するものを表現する
*ブラウザのDOM要素と異なり、React ブラウザのDOM要素と異なり、[[React]] Elements はプレーンなオブジェクトで生成のコストは小さい*[[React]] DOMは、DOMを[[React DOMは、DOMをReact ]] Elementsに一致するように取り扱う====1つの要素をDOMの中にレンダリング1つの要素を[[DOM]]の中にレンダリング====*HTMLどこかに記述する、以下のDIV要素をroot [[HTML]]どこかに記述する、以下のDIV要素をroot DOM ノードと呼ぶ*[[React ]] DOM が管理するすべてが、この要素の中にある <&lt;div id="root"><&gt;&lt;/div>&gt;====React要素の更新[[React]]要素の更新====*React要素は不変。一旦生成したら、子要素、属性などは変更できない。[[React]]要素は不変。一旦生成したら、子要素、属性などは変更できない。*UIを更新するには、新しい要素を作成し、ReactDOMUIを更新するには、新しい要素を作成し、[[React]]DOM.rendar()に引き渡す。
function tick() {
const element = (<&lt;div>&gt;{(new Date()).toLocaleTimeString()}<&lt;/div>&gt;); ReactDOM[[React]]DOM.render(
element,
document.getElementById('root')
setInterval(tick,1000);
[[File:1092_react07.jpg]]
<&lt;blockquote>通常のReact アプリケーションでは、ReactDOM&gt;通常の[[React]] アプリケーションでは、[[React]]DOM.rendar()は 一度しか呼びださない。<&lt;/blockquote>&gt;====Reactは必要なもののみ更新する[[React]]は必要なもののみ更新する====*[[React ]] DOMは、要素および子要素を前の状態と比較し、DOMの更新が必要な個所にのみ適用する。
*ブラウザツールで、上記のソースコードを確認する
[[File:1093_react08.jpg]]
<&lt;blockquote>&gt;毎tick()の呼び出しで、すべてのUIツリーを生成するよう記述してるが、変更が発生したテキストノードのみReact の呼び出しで、すべてのUIツリーを生成するよう記述してるが、変更が発生したテキストノードのみ[[React]] DOMにより更新されている。<&lt;/blockquote>&gt;
===コンポーネントと Props===
*コンポーネントはUIを独立し再利用可能な部分に分割する。
*概念的にコンポーネントはJavaScriptの関数のようなもの。概念的にコンポーネントは[[JavaScript]]の関数のようなもの。*コンポーネントはpropsと呼ばれる任意の入力を受け付け、React コンポーネントはpropsと呼ばれる任意の入力を受け付け、[[React]] Elementを返す。
====コンポーネントの機能とクラス====
*JavaScriptの関数としてコンポーネントを定義する[[JavaScript]]の関数としてコンポーネントを定義する*この関数は有効なReactコンポーネント、なぜなら、単一のprops引数を引数として取り、React この関数は有効な[[React]]コンポーネント、なぜなら、単一のprops引数を引数として取り、[[React]] Elementを返す。
*このようなコンポーネントを"functional"と呼ぶ。
function Welcome(props) {
return <&lt;h1>&gt;Hello,{props.name}<&lt;/h1>&gt;;
}
*ES6のクラスをコンポーネントの定義として利用できる
class Welcome extends [[React]].Component {
render() {
return <&lt;h1>&gt;Hello,{props.name}<&lt;/h1>&gt;;
}
}
*上記2つのコンポーネントはReactの視点からは同じ上記2つのコンポーネントは[[React]]の視点からは同じ
====コンポーネントのレンダリング====
*Elementは、ユーザー定義コンポーネントも表すことができる
function Welcome(props) {
return <&lt;h1>&gt;Hello,{props.name}<&lt;/h1>&gt;;
}
const element = <&lt;Welcome name='Hiroto' />&gt; ReactDOM[[React]]DOM.render(
element,
document.getElementById('root')
);
*Reactがユーザー定義コンポーネントを表示するときに、JSXの属性からコンポーネントへ[[React]]がユーザー定義コンポーネントを表示するときに、JSXの属性からコンポーネントへ"props"としてオブジェクトが渡される。
<&lt;blockquote>コンポーネント名はいつも大文字から始める。DOM &gt;コンポーネント名はいつも大文字から始める。[[DOM]] タグは、<&lt;div /> &gt; だが、<&lt;Welcome /> &gt; はコンポーネントを表現する。Welcomeがスコープに存在すること。<&lt;/blockquote>&gt;
====コンポーネントの構成====
*コンポーネントはその出力において、他のコンポーネントに影響を与えることができる
*同じコンポーネントをどんなレベルの詳細にも抽象的に利用できる、ボタン、フォーム、ダイアログ、スクリーン
*Reactでこれらは、一般にコンポーネントで表現される[[React]]でこれらは、一般にコンポーネントで表現される
function Welcome(props) {
return <&lt;h1>&gt;Hello,{props.name}<&lt;/h1>&gt;;
}
function App() {
return ( <&lt;div>&gt; <&lt;Welcome name="Yagi"/>&gt; <&lt;Welcome name="Kaela"/>&gt; <&lt;Welcome name="Hiroto"/>&gt; <&lt;/div> &gt; );
}
ReactDOM[[React]]DOM.render( <&lt;App />&gt;,
document.getElementById('root')
);
*一般的に新しいReactアプリケーションは、一つのAppコンポーネントを最上位に持つ。既存のアプリケーションにReactを統合する場合は、小さなコンポーネント、例えばButtonなど、ボトムアップから開始し、徐々にView階層の最上位にいたる。一般的に新しい[[React]]アプリケーションは、一つのAppコンポーネントを最上位に持つ。既存のアプリケーションに[[React]]を統合する場合は、小さなコンポーネント、例えばButtonなど、ボトムアップから開始し、徐々にView階層の最上位にいたる。
<&lt;blockquote>&gt;コンポーネントは、一つのroot要素を返さなければならない。上記で、Welcome要素を div に含めたのはこのため<&lt;/blockquote>&gt;
====Propsは読み取り専用====
**Reactはかなりフレキシブルだが、1つ厳格なルールがある。function [[React]]はかなりフレキシブルだが、1つ厳格なルールがある。function だろうと class だろうとコンポーネントはpropsを編集できない。
===状態とライフサイクル===
*次のClockコンポーネントを再利用可能にカプセル化する
function Clock(props) {
return (
<&lt;div>&gt; <&lt;h2>&gt;{props.date.toLocaleTimeString()}<&lt;/h2>&gt; <&lt;/div>&gt;
);
}
function tick() {
ReactDOM[[React]]DOM.render( <&lt;Clock date={new Date()} />&gt;,
document.getElementById('root')
);
*クラス宣言したコンポーネントにはいくつかの追加的な機能があるが、local state はこれにあたる
====関数をクラスに変更する====
#[[React]].Component を継承して同名のES6クラスを作成する
#render()メソッドを作成し、処理を移動、functionを削除
#propsをthis.propsに変更
class Clock extends [[React]].Component {
render() {
return (
<&lt;div>&gt; <&lt;h2>&gt;{this.props.date.toLocaleTimeString()}<&lt;/h2>&gt; <&lt;/div>&gt;
);
}
#render()メソッドの中の、this.props.date を this.state.date に変更
#クラスにコンストラクタを追加し、this.stateの初期状態を記述する
#<&lt;Clock date={new Date()} /> &gt; から dateを削除 class Clock extends [[React]].Component {
constructor(props) {
super(props);
render() {
return (
<&lt;div>&gt; <&lt;h2>&gt;{this.state.date.toLocaleTimeString()}<&lt;/h2>&gt; <&lt;/div>&gt;
);
}
====クラスにライフサイクルメソッドを追加する====
*多くのコンポーネントを使用するアプリケーションでは、破棄されたコンポーネントのリソースの解放が重要
*ClockがDOMに最初にレンダリングされるときには、必ずタイマーをセットアップしたい。これをReactでは、ClockがDOMに最初にレンダリングされるときには、必ずタイマーをセットアップしたい。これを[[React]]では、"mounting" という*また、ClockがDOMから取り除かれるときには、タイマーをクリアしたい。これをReactでは、また、ClockがDOMから取り除かれるときには、タイマーをクリアしたい。これを[[React]]では、"unmounting"という
*コンポーネントが、mount/unmount されるときに実行される特別なメソッドをクラスに宣言できる
*componentDidMount()、componentWillUnmount() これらのメソッドはライフサイクルフックと呼ばれる
*どのようにtimer IDを thisに保存するか
**this.propsがReactによりセットアップされる間、thispropsが[[React]]によりセットアップされる間、this.stateは特別な意味を持つ
**表示に使用しないならば、クラスに自由にフィールドを追加できる
**render()の中では、それらは利用できないし、ステートも持たない
*this.setState()でローカルコンポーネントの状態を更新する
class Clock extends [[React]].Component {
constructor(props) {
super(props);
componentDidMount() {
this.timerID = setInterval(
() => &gt; this.tick(),1000
);
}
render() {
return (
<&lt;div>&gt; <&lt;h2>&gt;{this.state.date.toLocaleTimeString()}<&lt;/h2>&gt; <&lt;/div>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;Clock />&gt;,
document.getElementById('root')
);
// 正しい
this.setSatate({comment:'Hello'});
<&lt;blockquote>&gt;this.stateを割り当てることができるのは、コンストラクタのみ<&lt;/blockquote>&gt;
=====stateは、非同期に更新される=====
*Reactは、複数のsetState[[React]]は、複数のsetState() をパフォーマンスのためにまとめて一度に処理する。
*このため、this.propsとthis.stateは非同期に更新される
*これらの値を信頼して、次の状態への計算を行うべきではない
*関数は、ひとつ前の状態(state)を最初の引数として、更新時のpropsを2つ目の引数として取る
// 正しい
this.setState((prevState, props) => &gt; ({
counter: prevState.counter + prpos.increament
}));
});
=====状態の更新はマージされる=====
*setState()を呼び出すと、Reactは、現在のstateに提供したオブジェクトをマージするを呼び出すと、[[React]]は、現在のstateに提供したオブジェクトをマージする
*例えば、いくつかの独立した変数を含む場合
constructor(props) {
*これらを別のsetState() で更新
componentDidMount() {
fetchPosts().then(response => &gt; { this.setState({ posts: response.posts }); }); fetchComments().then(response => &gt; { this.setState({ commentss: response.comments }); });
}
*マージはシャローなので、setState({comment}) は、this.state.posts を損なわずに、this.state.comments を置き換える
*状態はしばしばローカルから呼び出されるかカプセル化されていて、他からアクセスできない。
*コンポーネントは、自身の状態をpropsを通して子コンポーネントに渡す
<&lt;h2>&gt;It is {this.state.date.toLocalTimeString()}.<&lt;/h2>&gt;
*これは、ユーザー定義コンポーネントでも動作する
<&lt;FormattedDate date={this.state.date} />&gt;
*FormattedDateコンポーネントは、propsにdateを受け取り、Clockの状態が何かは知らない。
function FormatterDate(props) {
return <&lt;h2>&gt;It is {props.date.toLocaleTimeString()}.<&lt;/h2>&gt;;
}
*これは一般的に、トップダウン、もしくは、ユニディレクショナル データフローという
*データやUIは状態に由来し、ツリーのより下のコンポーネントにのみ影響を与えることができる
===イベントの処理===
*[[React ]] 要素のイベント処理は、DOMでの処理ととても似ているが、いくつかシンタックスの差異がある。**Reactイベントは、ロウアーケースではなく、キャメルケース[[React]]イベントは、ロウアーケースではなく、キャメルケース
**JSXでは、stringではなく、関数をイベントハンドラーとして渡す。
=====[[HTML]]===== <&lt;button onclick="test()" />&gt;=====[[React]]===== <&lt;button onClick={test} />&gt;
*もう一つの違いは、Reactでは、falseを返しデフォルトのふるまいを防止することができない。もう一つの違いは、[[React]]では、falseを返しデフォルトのふるまいを防止することができない。
*明示的に、preventDefault を呼び出す必要がある。
=====HTMLでデフォルトの新しいページを開くリンクのふるまいを防止する[[HTML]]でデフォルトの新しいページを開くリンクのふるまいを防止する===== <&lt;a href="#" onclick="console.log('hoge'); return false" >&gt;Click<&lt;/a>&gt;=====[[React]]=====
function ActionLink() {
function handleClick(e) {
}
return (
<&lt;a href="#" onClick={handleClick} >&gt;Click<&lt;/a>&gt;
)
}
*e は、本物ではないイベント。Reactでは、[https://www.w3.org/TR/DOM-Level-3-Events/ W3C]に合わせるために定義している。
*なので、ブラウザの互換性を心配する必要はない。[https://facebook.github.io/react/docs/events.html リファレンス]を参照
*Reactでは、addEventListenerを通常呼び出す必要はない。要素が最初にレンダリングされるときに提供される[[React]]では、addEventListenerを通常呼び出す必要はない。要素が最初にレンダリングされるときに提供される
*ES6のクラスを使用するときの一般的なパターン、例えば、Toggle ボタン
class Toggle extends [[React]].Component {
constructor(props) {
super(props);
}
handleClick() {
this.setState(prevStae => &gt; ({
isToggleOn: !prevStae.isToggleOn
}));
render() {
return (
<&lt;button onClick={this.handleClick} >&gt;
{this.state.isToggleOn?"ON":"OFF"}
<&lt;/button>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;Toggle />&gt;,
document.getElementById('root')
);
*コンストラクタでバインドするか、プロパティイニシャライザでバインドすることを推奨する。
===条件付きのレンダリング===
*Reactでは、必要なら、振る舞いがカプセルかされた他と異なったコンポーネントを作成できる。[[React]]では、必要なら、振る舞いがカプセルかされた他と異なったコンポーネントを作成できる。*Reactの条件付きレンダリングは、JavaScriptの条件が動作するのと同じ方法で動作する。Reactの条件付きレンダリングは、[[JavaScript]]の条件が動作するのと同じ方法で動作する。*JavaScriptのifのような演算子もしくは、条件演算子は、現在の状態を表した要素を作成するための、ReactがUIをそれに一致させることを許す。[[JavaScript]]のifのような演算子もしくは、条件演算子は、現在の状態を表した要素を作成するための、ReactがUIをそれに一致させることを許す。
=====以下の2つのコンポーネントについて考える=====
*ユーザーがログインしているか否かによって使い分けたい。
*isLoggedIn により、異なるレンダリングがなされる。
function UserGreeting(props){
return <&lt;h1>&gt;Welcome to back!<&lt;/h1>&gt;
}
function GuestGreeting(props) {
return <&lt;h1>&gt;Please Sign up!<&lt;/h1>&gt;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <&lt;UserGreeting />&gt;
} else {
return <&lt;GuestGreeting />&gt;
}
}
ReactDOM[[React]]DOM.render( <&lt;Greeting isLoggedIn={true} />&gt;,
document.getElementById('root')
);
function LoginButton(props) {
return (
<&lt;button onClick={props.onClick} >&gt;
Login
<&lt;/button>&gt;
);
}
function LogoutButton(props) {
return (
<&lt;button onClick={props.onClick} >&gt;
Logout
<&lt;/button>&gt;
);
}
class LoginControl extends [[React]].Component {
constructor(props) {
super(props);
let button = null;
if (isLoggedIn) {
button = <&lt;LogoutButton onClick={this.handleLogoutClick} />&gt;
} else {
button = <&lt;LoginButton onClick={this.handleLoginClick} />&gt;
}
return (<&lt;div>&gt;{button}<&lt;/div>&gt;);
}
}
ReactDOM[[React]]DOM.render( <&lt;LoginControl />&gt;,
document.getElementById('root')
);
[[File:1085_react_debug.jpg]]
====インラインif と 論理 && 演算子====
*true && 演算子の場合評価され、false && の場合、falseとなりReactは無視するの場合、falseとなり[[React]]は無視する
function MailBox(props) {
const unreadMessages = props.unreadMessages;
return (
<&lt;div>&gt; <&lt;h1>&gt;Hello!<&lt;/h1>&gt; {unreadMessages.length > &gt; 0 && <&lt;h2>&gt;
You have {unreadMessages.length} unread messages.
<&lt;/h2>&gt;
}
<&lt;/div>&gt;
);
}
const messages = ['message1','message2'];
ReactDOM[[React]]DOM.render( <&lt;MailBox unreadMessages={messages} />&gt;,
document.getElementById('root')
);
*条件 ? true : false
function UserGreeting(props){
return <&lt;h1>&gt;Welcome to back!<&lt;/h1>&gt;
}
function GuestGreeting(props) {
return <&lt;h1>&gt;Please Sign up!<&lt;/h1>&gt;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
return (
<&lt;div>&gt;
{isLoggedIn ? (
<&lt;UserGreeting />&gt;
) : (
<&lt;GuestGreeting />&gt;
)
}
<&lt;/div>&gt;
);
}
ReactDOM[[React]]DOM.render( <&lt;Greeting isLoggedIn={false} />&gt;,
document.getElementById('root')
);
}
return (
<&lt;div>&gt;Warning!<&lt;/div>&gt;
);
}
class Page extends [[React]].Component {
constructor(props) {
super(props);
}
handleToggleClick() {
this.setState(prevState =>&gt;({showWarning : !prevState.showWarning}));
}
render() {
return (
<&lt;div>&gt; <&lt;WarningBanner warn={this.state.showWarning} />&gt; <&lt;button onClick={this.handleToggleClick}>&gt;
{this.state.showWarning ? 'Hide' : 'Show'}
<&lt;/button>&gt; <&lt;/div>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;Page />&gt;,
document.getElementById('root')
);
[[File:1095_react10.jpg]]
===リストとキー===
=====JavaScriptでリストの変換には、map[[JavaScript]]でリストの変換には、map()を利用する=====
const numbers = [1,2,3,4,5];
const doubled = numbers.map((number)=> &gt; number * 2);
console.log(doubled)
> &gt; [2, 4, 6, 8, 10]*[[React ]] では同様に配列をリストに変換する
====複数のコンポーネントをレンダリングする====
const fruits = ['apple','orange','grape','banana'];
const listItems = fruits.map((fruit) => <&gt; &lt;li>&gt;{fruit}<&lt;/li>&gt;); ReactDOM[[React]]DOM.render( <&lt;ol>&gt;{listItems}<&lt;/ol>&gt;,
document.getElementById('root')
);
=====Keys=====
*keyを指定しないと警告がでる
*keyは、Reactが、どのアイテムが登録、変更、削除されたのか特定するのに役立つkeyは、[[React]]が、どのアイテムが登録、変更、削除されたのか特定するのに役立つ
*文字列で兄弟間でユニークな値を設定するのが望ましい
function FruitList(props) {
const fruits = props.fruits;
const listItems = fruits.map((fruit) => <&gt; &lt;li key={fruit}>&gt;{fruit}<&lt;/li>&gt;);
return (
<&lt;ol>&gt;{listItems}<&lt;/ol> &gt;
);
}
const fruits = ['apple','orange','grape','banana'];
ReactDOM[[React]]DOM.render( <&lt;FruitList fruits={fruits}/>&gt;,
document.getElementById('root')
);
*兄弟間で同じKeyを持つとエラーとなる
function ListItem(props) {
// この<&lt;li> &gt; にKeyを設定するのは、ここがルートになるため間違い return <&lt;li>&gt;{props.value}<&lt;/li>&gt;
}
function FruitList(props) {
const fruits = props.fruits;
// <&lt;ListItem>&gt;の配列となるため、ここでKeyを指定するのが正しい const listItems = fruits.map((fruit) => <&gt; &lt;ListItem key={fruit} value={fruit} />&gt;);
return (
<&lt;ol>&gt;{listItems}<&lt;/ol> &gt;
);
}
const fruits = ['apple','orange','grape','banana'];
ReactDOM[[React]]DOM.render( <&lt;FruitList fruits={fruits}/>&gt;,
document.getElementById('root')
);
*中括弧のインラインにmap()を置くことができる
function ListItem(props) {
return <&lt;li>&gt;{props.value}<&lt;/li>&gt;
}
function FruitList(props) {
const fruits = props.fruits;
return (
<&lt;ol>&gt;{fruits.map((fruit) => <&gt; &lt;ListItem key={fruit} value={fruit} />&gt;)}<&lt;/ol> &gt;
);
}
const fruits = ['apple','orange','grape','banana'];
ReactDOM[[React]]DOM.render( <&lt;FruitList fruits={fruits}/>&gt;,
document.getElementById('root')
);
===Form===
*HTML Formは、Reactでは、少し他のDOMとは動作が異なる。Formは、[[React]]では、少し他のDOMとは動作が異なる。
*なぜなら Fromは通常内部状態をもつから。
====コントロールされたコンポーネント====
*HTMLでFormは、自身の状態を維持しユーザー入力に基づいて状態を更新する。[[HTML]]でFormは、自身の状態を維持しユーザー入力に基づいて状態を更新する。*Reactでは、変化可能な状態はコンポーネントのstateプロパティに保持し、setState[[React]]では、変化可能な状態はコンポーネントのstateプロパティに保持し、setState()からのみ更新される。*"single source of truth"としてReact として[[React]] stateを作成することにより2つを結びつけることができる。*ReactコンポーネントはFormまたコントロールでユーザー入力により、何が起きたかを描画する。[[React]]コンポーネントはFormまたコントロールでユーザー入力により、何が起きたかを描画する。*input Form 要素の値は、Reactによりこの方法で制御される。要素の値は、[[React]]によりこの方法で制御される。
*これは、「コントロールされたコンポーネント」と呼ばれる。
class NameForm extends [[React]].Component {
constructor(props) {
super(props);
render() {
return(
<&lt;form onSubmit={this.handleSubmit}>&gt; <&lt;label>&gt;Name: <&lt;input type="text" value={this.state.value} onChange={this.handleChange} /><&gt;&lt;/label>&gt; <&lt;input type="submit" value="Submit"/>&gt; <&lt;/form>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;NameForm />&gt;,
document.getElementById('root')
);
[[File:1097_react12.jpg]]
*valueが、Form要素に設定されると、表示されるvalueは、常にthis.state.valueとなる
*すべてのキーストロークで、handleChangeが起動し、Reactのstateを更新するすべてのキーストロークで、handleChangeが起動し、[[React]]のstateを更新する
*表示されるvalueも更新される
handleChange(event) {
}
====textarea/select タグ====
class SelectParts extends [[React]].Component {
constructor(props){
super(props);
render(){
return(
<&lt;label>&gt;Select: <&lt;select value={this.state.value} onChange={this.handleChange}>&gt; <&lt;option value="grapefruit">&gt;Grape Fruit<&lt;/option>&gt; <&lt;option value="lime">&gt;Lime<&lt;/option>&gt; <&lt;option value="coconuts">&gt;Coconuts<&lt;/option>&gt; <&lt;option value="mango">&gt;Mango<&lt;/option>&gt; <&lt;/select>&gt; <&lt;/label>&gt;
);
}
}
class TextareaParts extends [[React]].Component {
constructor(props){
super(props);
render(){
return (
<&lt;label>&gt;Textarea:<&lt;textarea value={this.state.value} onChange={this.handleChange} /><&gt;&lt;/label>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;div>&gt; <&lt;SelectParts />&gt; <&lt;TextareaParts />&gt; <&lt;/div>&gt;,
document.getElementById('root')
);
*ハンドラー関数で、event.target.name の値に基づいて、どの要素か判定
*ES6 [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names 計算されたプロパティ名]構文をkey状態を更新するのに使用
class Reservation extends [[React]].Component {
constructor(props) {
super(props);
render(){
return (
<&lt;form>&gt; <&lt;label>&gt;Is going:<&lt;input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange}/><&gt;&lt;/label>&gt; <&lt;br />&gt; <&lt;label>&gt;Number of guests:<&lt;input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange}/><&gt;&lt;/label>&gt; <&lt;/form>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;div>&gt; <Reservation &lt;[[R]]eservation />&gt; <&lt;/div>&gt;,
document.getElementById('root')
);
=====水が沸騰しているかどうかの計算を行う。=====
function BoilingVerdict(props) {
if (props.celsius >&gt;= 100) { return <&lt;p>&gt;The water would boil.<&lt;/p>&gt;;
}
return <&lt;p>&gt;The water would not boil.<&lt;/p>&gt;
}
class Calculator extends [[React]].Component {
constructor(props) {
super(props);
const temprature = this.state.temprature;
return (
<&lt;fieldset>&gt; <&lt;legend>&gt;Enter temprature in Celsius:<&lt;/legend>&gt; <&lt;input value={temprature} onChange={this.handleChange} />&gt; <&lt;BoilingVerdict celsius={parseFloat(temprature)} /> &gt; <&lt;/fieldset>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;div>&gt; <&lt;Calculator />&gt; <&lt;/div>&gt;,
document.getElementById('root')
);
====2つ目の入力を追加する====
*華氏の入力を追加し同期させる
*Reactでstateを共有するには、共通の祖先に移動させることで実現でき、「状態の持ち上げ」という[[React]]でstateを共有するには、共通の祖先に移動させることで実現でき、「状態の持ち上げ」という
*TempratureInputのローカルstateをCalcuratorへ移動させる
*Calucratorの共有stateは、「真の情報源」となる
};
function BoilingVerdict(props) {
if (props.celsius >&gt;= 100) { return <&lt;p>&gt;The water would boil.<&lt;/p>&gt;;
}
return <&lt;p>&gt;The water would not boil.<&lt;/p>&gt;
}
function toCelsius(fahrenheit) {
return rounded.toString();
}
class TempratureInput extends [[React]].Component {
constructor(props) {
super(props);
const scale = this.props.scale;
return (
<&lt;fieldset>&gt; <&lt;legend>&gt;Enter temprature in {scaleName[scale]}:<&lt;/legend>&gt; <&lt;input value={temprature} onChange={this.handleChange} />&gt; <&lt;BoilingVerdict celsius={parseFloat(temprature)} /> &gt; <&lt;/fieldset>&gt;
);
}
}
class Calculator extends [[React]].Component {
constructor(props) {
super(props);
const fahrenheit = scale == 'c' ? tryConvert(temprature, toFahrenheit) : temprature;
return (
<&lt;div>&gt; <&lt;TempratureInput scale="c" temprature={celsius} onTempratureChange={this.handleCelsiumChange} />&gt; <&lt;TempratureInput scale="f" temprature={fahrenheit} onTempratureChange={this.handlFahrenheitChange}/>&gt; <&lt;BoilingVerdict celsius={parseFloat(celsius)} />&gt; <&lt;/div>&gt;
);
}
}
ReactDOM[[React]]DOM.render( <&lt;div>&gt; <&lt;Calculator />&gt; <&lt;/div>&gt;,
document.getElementById('root')
);
[[File:1100_react15.jpg]]
===コンポジションと継承===
*Reactは強力なコンポジションモデルをもつ。コンポーネントの再利用には継承よりコンポジションを推奨する[[React]]は強力なコンポジションモデルをもつ。コンポーネントの再利用には継承よりコンポジションを推奨する
====封じ込める====
*一部のコンポーネントは自身の子供を事前に知ることができない
*これは、特にサイドバーやダイアログなどボックスを表現するコンポーネント共通
*このようなコンポーネントには特別な子供propを使用し直接その要素に出力する
*<&lt;FancyBorder>&gt;の内側に何があっても、JSXタグはFancyBorderコンポーネントをprops.children として経由する <&lt;style type="text/css">&gt;
div.FancyBorder {
border : 2px dashed;
border-color: blue;
}
<&lt;/style>&gt;
function FancyBorder(props) {
return (
<&lt;div className={'FancyBorder FancyBorder-' + props.color}>&gt;
{props.children}
<&lt;/div>&gt;
);
}
function WelcomDialog() {
return (
<&lt;FancyBorder color="blue">&gt; <&lt;h1 className="Dialog-title">&gt;Welcome<&lt;/h1>&gt; <&lt;/FancyBorder>&gt;
);
}
ReactDOM[[React]]DOM.render( <&lt;div>&gt; <&lt;WelcomDialog />&gt; <&lt;/div>&gt;,
document.getElementById('root')
);
====特殊化====
*コンポーネントを他のコンポーネントの特殊なものとして考えることがある、例えば、WelcomDialogはDialogの特殊な例として。
*Reactでは、コンポジションを使って実現する[[React]]では、コンポジションを使って実現する
*クラスを用いても同様に記述できる
function Dialog(props) {
return (
<&lt;FancyBorder color="blue">&gt; <&lt;h1 className="Dialog-title">&gt;{props.title}<&lt;/h1>&gt; <&lt;/FancyBorder>&gt;
);
}
function FancyBorder(props) {
return (
<&lt;div className={'FancyBorder FancyBorder-' + props.color}>&gt;
{props.children}
<&lt;/div>&gt;
);
}
function WelcomDialog() {
return (
<&lt;Dialog title="Welcome" />&gt;
);
}
===[[React Router]]===*[[React Router]]===[[Redux]]===*[[Redux]]===[[Tips]]===
*[http://typea.info/blg/glob/2017/06/react.html React のシンタックスエラーをデバッグ]

案内メニュー