→ パート1:コースの概要、React、ReactDOM、JSXの人気の理由
→ パート2:機能コンポーネント
→ パート3:コンポーネントファイル、プロジェクト構造
→ パート4:親コンポーネントと子コンポーネント
→ パート5:TODOアプリケーションの作業の開始、スタイリングの基本
→ パート6:コースの一部の機能、JSXおよびJavaScriptについて
→ パート7:インラインスタイル
→ パート8:TODOアプリケーションの継続的な作業、コンポーネントのプロパティに精通
→ パート9:コンポーネントのプロパティ
→ パート10:コンポーネントのプロパティとスタイルの操作に関するワークショップ
→ パート11:動的マークアップ生成およびマップ配列メソッド
→ パート12:ワークショップ、TODOアプリケーションの作業の第3段階
→ パート13:クラスベースのコンポーネント
→ パート14:クラスベースのコンポーネント、コンポーネントのステータスに関するワークショップ
→ パート15:コンポーネントヘルスワークショップ
→ パート16:TODOアプリケーションの作業の第4段階、イベント処理
→ パート17:TODOアプリケーションの作業の第5段階、コンポーネントの状態の変更
→ パート18:TODOアプリケーションの作業の6番目の段階
→ パート19:コンポーネントのライフサイクルメソッド
パート20:条件付きレンダリングの最初のレッスン
→ パート21:条件付きレンダリングに関する2番目のレッスンとワークショップ
→ パート22:TODOアプリケーションの作業の第7段階、外部ソースからのデータのダウンロード
→ パート23:フォームの操作に関する最初のレッスン
→ パート24:2番目のフォームレッスン
→ パート25:フォームの操作に関するワークショップ
→ パート26:アプリケーションアーキテクチャ、コンテナ/コンポーネントパターン
→ パート27:コースプロジェクト
レッスン45.コースプロジェクト。 ミームジェネレーター
→ オリジナル
それで、コースプロジェクトに着きました。 ミームを生成するアプリケーションを作成しましょう。 このコマンドを使用して作成された標準のcreate-react-appプロジェクトから始めましょう。
npx create-react-app meme-generator
ここでは、その使用の機能に関する情報を見つけることができます。
このプロジェクトの作業の過程で、その一部を自分で実装してから、それらの説明を読むように求められます。 標準プロジェクトには、特に
index.js
および
App.js
に、特にボイラープレートコードが既にあり
App.js
。 このコードを完全に削除して、React-applicationsの標準メカニズムの実装で自分自身をテストするために自分で記述してみてください。
このプロジェクトでは、次のスタイルを使用するよう招待されています。
* { box-sizing: border-box; } body { margin: 0; background-color: whitesmoke; } header { height: 100px; display: flex; align-items: center; background: #6441A5; /* fallback for old browsers */ background: -webkit-linear-gradient(to right, #2a0845, #6441A5); /* Chrome 10-25, Safari 5.1-6 */ background: linear-gradient(to right, #2a0845, #6441A5); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ } header > img { height: 80%; margin-left: 10%; } header > p { font-family: VT323, monospace; color: whitesmoke; font-size: 50px; margin-left: 60px; } .meme { position: relative; width: 90%; margin: auto; } .meme > img { width: 100%; } .meme > h2 { position: absolute; width: 80%; text-align: center; left: 50%; transform: translateX(-50%); margin: 15px 0; padding: 0 5px; font-family: impact, sans-serif; font-size: 2em; text-transform: uppercase; color: white; letter-spacing: 1px; text-shadow: 2px 2px 0 #000, -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 0 2px 0 #000, 2px 0 0 #000, 0 -2px 0 #000, -2px 0 0 #000, 2px 2px 5px #000; } .meme > .bottom { bottom: 0; } .meme > .top { top: 0; } .meme-form { width: 90%; margin: 20px auto; display: flex; justify-content: space-between; } .meme-form > input { width: 45%; height: 40px; } .meme-form > button { border: none; font-family: VT323, monospace; font-size: 25px; letter-spacing: 1.5px; color: white; background: #6441A5; } .meme-form > input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input::-moz-placeholder { /* Firefox 19+ */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input:-ms-input-placeholder { /* IE 10+ */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input:-moz-placeholder { /* Firefox 18- */ font-family: VT323, monospace; font-size: 25px; text-align: cen }
これらのスタイルは、プロジェクトにすでにある
index.css
ファイルに
index.css
て、
index.js
ファイルに
index.css
ができます。
そのため、
index.js
ファイルと
App.js
ファイルが空になったという前提に基づいて、最初のタスクとして、
index.js
で
index.js
コードを記述し、
App.js
最も単純なコンポーネントを作成して
index.js
出力するよう
App.js
され
index.js
。
index.js
表示されるものは次のとおりです。
import React from "react" import ReactDOM from "react-dom" import './index.css' import App from "./App" ReactDOM.render(<App />, document.getElementById("root"))
ここで、
React
と
ReactDOM
をインポートし、
index.css
と
App
コンポーネントからスタイルをインポートします。 その後、
ReactDOM.render()
メソッドを使用して、
App
コンポーネントが形成するものを
root
識別子(
<div id="root"></div>
)を持つ
index.html
ページ要素に
ReactDOM.render()
。
App.js
ファイルは
App.js
のように
App.js
ます。
import React from "react" function App() { return ( <h1>Hello world!</h1> ) } export default App
次に、最も単純な機能コンポーネントを示します。
作業のこの段階では、プロジェクトは次のようになります。
ブラウザでのアプリケーション
ここで、コンポーネントの名前に対応する名前を持つ2つのファイルに、2つの新しいコンポーネントを作成します。
- アプリケーションヘッダーの表示に使用される
Header
コンポーネント。 -
MemeGenerator
コンポーネント。アプリケーションに割り当てられたメインタスクが解決されます。 つまり、ここでAPI呼び出しが行われます。 アプリケーションデータはここに保存されます。
これらのコンポーネントに割り当てられている機能を考えて、それらがどうあるべきかを考えてください。
Header.js
ファイルの内容は次の
Header.js
です。
import React from "react" function Header() { return ( <h1>HEADER</h1> ) } export default Header
このコンポーネントはアプリケーションのタイトルを表示するためだけに使用されるため、機能的なコンポーネントとして設計しました。
MemeGenerator.js
ファイルのコードは次の
MemeGenerator.js
です。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state ={} } render() { return ( <h1>MEME GENERATOR SECTION</h1> ) } } export default MemeGenerator
ここでは、
MemeGenerator
コンポーネントによって解決されるはずのタスクを考慮して、クラスに基づいたコンポーネントを使用します。 ここには、空のオブジェクトで状態を初期化するコンストラクターがあります。
これらのファイルを作成した後、それらを
App.js
にインポートし、これらのコンポーネントのインスタンスを使用する
App
機能コンポーネントからマークアップを返します。機能コンポーネントが複数の要素を返す場合、何かにラップする必要があることを忘れません。 私たちの場合、これは
<div>
です。 更新された
App.js
コードは次の
App.js
です。
import React from "react" import Header from "./Header" import MemeGenerator from "./MemeGenerator" function App() { return ( <div> <Header /> <MemeGenerator /> </div> ) } export default App
アプリケーションの外観を確認します。
ブラウザでのアプリケーション
それでは、
Header
コンポーネントに取り組みましょう。 ここでは、セマンティック要素HTML5
<header>
ます。 このタグには画像とテキストが含まれます。 これで、
Header.js
ファイルのコードは次のようになります。
import React from "react" function Header() { return ( <header> <img src="http://www.pngall.com/wp-content/uploads/2016/05/Trollface.png" alt="Problem?" /> <p>Meme Generator</p> </header> ) } export default Header
アプリの外観がどのように変化するかを次に示します。
ブラウザでのアプリケーション
アプリケーションのタイトルは、以前に
index.js
れていたスタイルに従って設計されています。 これで、
Header
コンポーネントの作業が完了しました。
MemeGenerator
コンポーネントを引き続き扱います。 これで、次のデータを書き込むことにより、このコンポーネントの状態を個別に初期化することができます。
- ミームの上部に表示されるテキスト(
topText
プロパティ)。 - ミームの下部に表示されるテキスト(
bottomText
プロパティ)。 - ランダム画像(リンクhttp://i.imgflip.com/1bij.jpgで初期化する必要がある
randomImage
プロパティ)。
これは、状態を初期化した後の
MemeGenerator.js
コードです。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg" } } render() { return ( <h1>MEME GENERATOR SECTION</h1> ) } } export default MemeGenerator
これで、アプリケーションの外観は影響を受けません。
APIへの呼び出しを使用します。APIへの呼び出しは、画像へのリンクを含むオブジェクトの配列を返し、それに基づいてミームを作成できます。 プロジェクトの作業のこの段階で、
MemeGenerator
コンポーネントに次の機能を実装するよう招待されます。
- API https://api.imgflip.com/get_memes/を呼び出します 。
- 応答で利用可能なデータを
response.data.memes
配列として新しい状態プロパティ(allMemeImgs
)に保存します。
ここでは、このAPIにアクセスするときに返されるJSONデータのフラグメントをより明確にするために:
{ "success":true, "data":{ "memes":[ { "id":"112126428", "name":"Distracted Boyfriend", "url":"https:\/\/i.imgflip.com\/1ur9b0.jpg", "width":1200, "height":800, "box_count":3 }, { "id":"87743020", "name":"Two Buttons", "url":"https:\/\/i.imgflip.com\/1g8my4.jpg", "width":600, "height":908, "box_count":2 }, { "id":"129242436", "name":"Change My Mind", "url":"https:\/\/i.imgflip.com\/24y43o.jpg", "width":482, "height":361, "box_count":2 }, …. ] } }
上記の問題を解決するには、アプリケーションの最初にコンポーネントが必要とするデータについて話しているという事実を考慮する必要があります。
したがって、それらをロードするには、
componentDidMount()
ライフサイクルメソッドを使用します。 ここでは、標準の
fetch()
メソッドを使用して、APIを呼び出します。 約束を返します。 データをロードすると、応答オブジェクトが利用可能になります。応答オブジェクトから
memes
配列を抽出し、空の配列で初期化された新しい状態プロパティ
allMemeImgs
に配置します。 このデータはまだ画面に表示されるものの形成に使用されていないため、配列の最初の要素をコンソールに出力して、データ読み込みメカニズムの正しい動作を確認します。
この作業段階での
MemeGenerator
コンポーネントのコードは次の
MemeGenerator
です。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data console.log(memes[0]) this.setState({ allMemeImgs: memes }) }) } render() { return ( <h1>MEME GENERATOR SECTION</h1> ) } } export default MemeGenerator
これは、データを正常にロードした後にコンソールに到達するものです。
ブラウザ内のアプリケーション、読み込まれた配列の最初の要素のコンソールへの出力
画像は多くのプロパティを使用して記述されていることに注意してください。 画像をダウンロードするためのリンクへのアクセスを提供する
url
プロパティのみを使用します。
コースの冒頭で、このアプリケーションの外観について説明しました。
ミームジェネレーター
特に、インターフェースにはテキストを入力するためのいくつかのフィールドがあり、画像の上下に表示されます。 ここで、フォームブランクがここに追加されるという点でこのコンポーネントの上記のコードと異なる、以下に示す
MemeGenerator
コンポーネントの更新されたコードに基づいて、いくつかのテキストフィールド
topText
および
bottomText
で作成するように
bottomText
。 これらは管理対象コンポーネントでなければならないことに注意してください。 それらに必要な属性を追加します。 これらのフィールドに
onChange
イベント
onChange
作成します。これらのフィールドでは、テキストを入力するときに対応する状態プロパティを更新する必要があります。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } render() { return ( <div> <form className="meme-form"> { // } <button>Gen</button> </form> </div> ) } } export default MemeGenerator
ところで、
render()
メソッドによって返されるコードにコメントを含めるために、このフラグメントをJavaScriptコードとして解釈する必要があることをシステムに示すために、コメントを中括弧で囲んだことに注意してください。
アプリケーションの作業のこの段階で取得する必要があるものは次のとおりです。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } this.handleChange = this.handleChange.bind(this) } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) } render() { return ( <div> <form className="meme-form"> <input type="text" name="topText" placeholder="Top Text" value={this.state.topText} onChange={this.handleChange} /> <input type="text" name="bottomText" placeholder="Bottom Text" value={this.state.bottomText} onChange={this.handleChange} /> <button>Gen</button> </form> </div> ) } } export default MemeGenerator
これで、アプリケーションページは次のようになります。
ブラウザでのアプリケーション
ヘルプテキストのあるフィールドのみが表示されますが、フィールドにデータを入力してもインターフェイスは変更されません。 ここで実装されているメカニズムの正しい動作を確認するには、
console.log()
コマンドを使用できます。
次に、イメージミームの表示を担当するアプリケーションの部分で作業してみましょう。 ミームの基礎として使用する予定の画像に関する情報を含む配列があることを思い出してください。 アプリケーションは、
Gen
ボタンを押して、この配列からランダムに画像を選択し、ミームを形成する必要があります。
MemeGenerator
コンポーネントの更新されたコードは次の
MemeGenerator
です。 ここで、
render()
メソッドのフォーム記述コードの下に、画像を表示する
<img>
要素とラベルを表示する
<h2>
要素を含む
<div>
要素があります。
<div>
および
<h2>
要素は、プロジェクトの作業の最初にプロジェクトに追加したスタイルを使用して装飾されます。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } this.handleChange = this.handleChange.bind(this) } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) } render() { return ( <div> <form className="meme-form"> <input type="text" name="topText" placeholder="Top Text" value={this.state.topText} onChange={this.handleChange} /> <input type="text" name="bottomText" placeholder="Bottom Text" value={this.state.bottomText} onChange={this.handleChange} /> <button>Gen</button> </form> <div className="meme"> <img align="center" src={this.state.randomImg} alt="" /> <h2 className="top">{this.state.topText}</h2> <h2 className="bottom">{this.state.bottomText}</h2> </div> </div> ) } } export default MemeGenerator
アプリは次のようになります。
ブラウザでのアプリケーション
状態を初期化した画像がここに表示されることに注意してください。
allMemeImgs
状態
allMemeImgs
保存されている画像はまだ使用していません。 テキストフィールドに何かを入力してみましょう。
ブラウザでのアプリケーション
ご覧のとおり、テキストを操作するアプリケーションサブシステムは期待どおりに機能します。 これで、
Gen
ボタンをクリックすることにより、画像データを含む配列からランダム画像が選択され、テキスト入力フィールドの下のページにある
<img>
要素にロードされることを確認するだけです。
この機能をアプリケーションに装備するには、次のタスクを実行します。 [
Gen
]ボタンをクリックすると起動するメソッドを作成します。 このメソッドは、
allMemeImgs
state
allMemeImgs
に情報が保存されている画像の1つを選択し、テキスト入力フィールドの下にある
<img>
要素でこの画像を表示できるアクションを実行する必要があります。
allMemeImgs
は画像を記述するオブジェクトの配列が格納され、この配列の各オブジェクトには
url
プロパティがあることに
allMemeImgs
。
この問題の解決策を提供するコードは次のとおりです。
import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } this.handleChange = this.handleChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) } handleSubmit(event) { event.preventDefault() const randNum = Math.floor(Math.random() * this.state.allMemeImgs.length) const randMemeImg = this.state.allMemeImgs[randNum].url this.setState({ randomImg: randMemeImg }) } render() { return ( <div> <form className="meme-form" onSubmit={this.handleSubmit}> <input type="text" name="topText" placeholder="Top Text" value={this.state.topText} onChange={this.handleChange} /> <input type="text" name="bottomText" placeholder="Bottom Text" value={this.state.bottomText} onChange={this.handleChange} /> <button>Gen</button> </form> <div className="meme"> <img align="center" src={this.state.randomImg} alt="" /> <h2 className="top">{this.state.topText}</h2> <h2 className="bottom">{this.state.bottomText}</h2> </div> </div> ) } } export default MemeGenerator
[
Gen
]ボタンは、他のボタンの場合と同様に、クリックされたときにイベントハンドラーに割り当てることができます。 ただし、このボタンがフォームの送信に使用されるという事実を考えると、フォームの
onSubmit
イベント
onSubmit
を使用する方が適切です。 このハンドラー
handleSubmit()
では、ページがリロードされる標準のフォーム
event.preventDefault()
手順をキャンセルするために、そこに来る
event.preventDefault()
イベントのメソッドを呼び出します。 次に、0から
allMemeImgs
配列の最後の要素のインデックスに対応する値までの範囲の乱数を取得し、この番号を使用して、対応するインデックスを持つ要素を参照します。 オブジェクトである要素に目を向けると、このオブジェクト
url
プロパティを取得し、状態プロパティ
randomImg
ます。 その後、コンポーネントが再レンダリングされ、ページの外観が変更されます。
ブラウザのアプリケーションページ
コースプロジェクトが完了しました。
まとめ
このレッスンでは、Reactをマスターしながら学んだことを使用するアプリケーションを作成しました。 次回は、最新のReactアプリケーションの開発について話し、Reactと連携して実践できるプロジェクトのアイデアについて議論します。
親愛なる読者! このコースプロジェクトを完了する際に問題が発生しましたか?