Reactトレーニングコースパート27:コースプロジェクト

Reactトレーニングコースの翻訳のこの部分では、ミームジェネレーターを作成するように求められます。



画像



パート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.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



コンポーネントを引き続き扱います。 これで、次のデータを書き込むことにより、このコンポーネントの状態を個別に初期化することができます。





これは、状態を初期化した後の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にアクセスするときに返される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と連携して実践できるプロジェクトのアイデアについて議論します。



親愛なる読者! このコースプロジェクトを完了する際に問題が発生しましたか?






All Articles