Kursus Pelatihan Bereaksi Bagian 27: Proyek Kursus

Di bagian terjemahan kursus pelatihan Bereaksi ini, Anda diminta untuk membuat generator meme.

gambar

Bagian 1: ikhtisar kursus, alasan popularitas React, ReactDOM dan JSX
Bagian 2: komponen fungsional
Bagian 3: file komponen, struktur proyek
Bagian 4: komponen induk dan anak
Bagian 5: mulai bekerja pada aplikasi TODO, dasar-dasar gaya
Bagian 6: tentang beberapa fitur kursus, JSX dan JavaScript
Bagian 7: gaya inline
Bagian 8: terus bekerja pada aplikasi TODO, terbiasa dengan sifat-sifat komponen
Bagian 9: properti komponen
Bagian 10: Workshop bekerja dengan properti komponen dan gaya
Bagian 11: pembuatan markup dinamis dan metode susunan peta
Bagian 12: lokakarya, pekerjaan tahap ketiga pada aplikasi TODO
Bagian 13: komponen berbasis kelas
Bagian 14: lokakarya tentang komponen berbasis kelas, status komponen
Bagian 15: bengkel kesehatan komponen
Bagian 16: tahap keempat dari pengerjaan aplikasi TODO, penanganan acara
Bagian 17: tahap kelima bekerja pada aplikasi TODO, memodifikasi status komponen
Bagian 18: tahap keenam dari pengerjaan aplikasi TODO
Bagian 19: metode siklus hidup komponen
Bagian 20: pelajaran pertama dalam rendering bersyarat
Bagian 21: pelajaran kedua dan lokakarya tentang rendering bersyarat
Bagian 22: tahap ketujuh bekerja pada aplikasi TODO, mengunduh data dari sumber eksternal
Bagian 23: pelajaran pertama tentang bekerja dengan formulir
Bagian 24: Pelajaran Bentuk Kedua
Bagian 25: Workshop bekerja dengan formulir
Bagian 26: arsitektur aplikasi, pola Container / Komponen
Bagian 27: proyek kursus

Pelajaran 45. Proyek kursus. Generator Meme


Asli

Jadi kami sampai di proyek kursus. Mari kita buat aplikasi yang akan menghasilkan meme. Mari kita mulai dengan proyek aplikasi create-react-app standar yang dibuat menggunakan perintah ini:

npx create-react-app meme-generator 

Di sini Anda dapat menemukan informasi tentang fitur penggunaannya.

Dalam proses pengerjaan proyek ini, Anda akan diminta untuk mengimplementasikan sendiri beberapa bagiannya, dan kemudian membaca penjelasan tentangnya. Proyek standar sudah memiliki kode boilerplate yang terletak, khususnya, dalam file index.js dan App.js Anda dapat menghapus kode ini sepenuhnya dan mencoba menulisnya sendiri untuk menguji diri Anda dalam penerapan mekanisme standar React-aplikasi.

Dalam proyek ini, Anda diundang untuk menggunakan gaya berikut:

 * {   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 } 

Gaya-gaya ini dapat dimasukkan dalam file index.css sudah ada dalam proyek dan index.css dalam file index.js .

Jadi, berdasarkan asumsi bahwa file index.js dan App.js sekarang kosong, Anda, sebagai tugas pertama, diundang untuk menulis kode index.js , membuat komponen paling sederhana di App.js dan mengeluarkannya ke index.js .

Inilah yang seharusnya muncul di index.js :

 import React from "react" import ReactDOM from "react-dom" import './index.css' import App from "./App" ReactDOM.render(<App />, document.getElementById("root")) 

Di sini kita mengimpor React dan ReactDOM , mengimpor gaya dari index.css dan komponen App . Setelah itu, menggunakan metode ReactDOM.render() , kami ReactDOM.render() apa yang komponen App bentuk menjadi elemen halaman index.html dengan pengidentifikasi root ( <div id="root"></div> ).

App.js inilah App.js file App.js :

 import React from "react" function App() {   return (       <h1>Hello world!</h1>   ) } export default App 

Di sini sekarang disajikan komponen fungsional yang paling sederhana.

Pada tahap ini, proyek terlihat seperti yang ditunjukkan di bawah ini.


Aplikasi di browser

Sekarang buat dua komponen baru, dalam dua file yang namanya sesuai dengan nama-nama komponen:

  • Komponen Header yang akan digunakan untuk menampilkan header aplikasi.
  • Komponen MemeGenerator , di mana tugas utama yang ditetapkan untuk aplikasi akan diselesaikan. Yaitu, panggilan ke API akan dilakukan di sini. Data aplikasi akan disimpan di sini.

Mempertimbangkan fungsi apa yang ditugaskan pada komponen-komponen ini, pikirkan tentang apa yang seharusnya.

Berikut ini isi file Header.js :

 import React from "react" function Header() {   return (       <h1>HEADER</h1>   ) } export default Header 

Karena komponen ini hanya akan digunakan untuk menampilkan header aplikasi, kami mendesainnya sebagai komponen fungsional.

Berikut ini kode untuk file 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 

Di sini, dengan mempertimbangkan tugas-tugas yang seharusnya diselesaikan dengan menggunakan komponen MemeGenerator , kami akan menggunakan komponen berdasarkan kelas. Ada konstruktor di sini di mana kita menginisialisasi keadaan dengan objek kosong.

Setelah membuat file-file ini, kami mengimpornya ke App.js dan mengembalikan markup dari komponen fungsional App , yang menggunakan instance dari komponen-komponen ini, tidak lupa bahwa jika komponen fungsional mengembalikan beberapa elemen, mereka harus dibungkus dengan sesuatu. Dalam kasus kami, ini adalah <div> . Berikut adalah kode App.js diperbarui:

 import React from "react" import Header from "./Header" import MemeGenerator from "./MemeGenerator" function App() {   return (       <div>           <Header />           <MemeGenerator />       </div>   ) } export default App 

Periksa tampilan aplikasi.


Aplikasi di browser

Sekarang mari kita bekerja pada komponen Header . Di sini kita akan menggunakan elemen semantik HTML5 <header> . Tag ini akan berisi gambar dan teks. Sekarang kode file Header.js akan terlihat seperti ini:

 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 

Begini cara tampilan aplikasi akan berubah.


Aplikasi di browser

Judul aplikasi dirancang sesuai dengan gaya yang sebelumnya index.js dalam index.js . Bekerja pada komponen Header sekarang selesai.

Kami akan terus berurusan dengan komponen MemeGenerator . Sekarang Anda diundang untuk secara mandiri menginisialisasi keadaan komponen ini dengan menulis data berikut ini:

  • Teks ditampilkan di bagian atas meme (properti topText ).
  • Teks ditampilkan di bagian bawah meme (properti bottomText ).
  • Gambar acak (properti randomImage yang perlu diinisialisasi dengan tautan http://i.imgflip.com/1bij.jpg ).

Inilah yang akan menjadi kode MemeGenerator.js setelah menginisialisasi status:

 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 

Sekarang penampilan aplikasi tidak akan terpengaruh.

Kami akan menggunakan panggilan ke API, yang mengembalikan array objek yang berisi tautan ke gambar, berdasarkan meme mana yang dapat dibuat. Pada tahap kerja proyek ini, Anda diundang untuk mengimplementasikan fungsionalitas berikut dalam komponen MemeGenerator :


Di sini, untuk membuatnya lebih jelas, sebuah fragmen data JSON dikembalikan saat mengakses API ini:

 {   "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        },        ….  ]  } } 

Memecahkan masalah yang diajukan di atas, perlu untuk mempertimbangkan fakta bahwa kita berbicara tentang data yang dibutuhkan komponen pada awal aplikasi.

Oleh karena itu, untuk memuatnya, kami akan menggunakan metode daur hidup componentDidMount() . Di sini kita, menggunakan metode fetch() standar fetch() , akan memanggil API. Itu mengembalikan janji. Setelah memuat data, objek respons akan tersedia untuk kita, dari situ kita mengekstrak array memes dan memasukkannya ke dalam properti state baru allMemeImgs , diinisialisasi dengan array kosong. Karena data ini belum digunakan untuk membentuk sesuatu yang ditampilkan di layar, kami akan mencetak elemen pertama dari array ke konsol untuk memeriksa operasi yang benar dari mekanisme pemuatan data.

Berikut adalah kode komponen MemeGenerator pada tahap kerja ini:

 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 

Inilah yang sampai ke konsol setelah berhasil memuat data.


Aplikasi di browser, output ke konsol dari elemen pertama dari array yang dimuat

Perhatikan bahwa gambar dijelaskan menggunakan banyak properti. Kami hanya akan menggunakan properti url , yang memberikan akses ke tautan untuk mengunduh gambar.

Pada awal kursus, kami berbicara tentang bagaimana tampilan aplikasi ini.


Generator Meme

Secara khusus, antarmuka memiliki beberapa bidang untuk memasukkan teks, yang akan ditampilkan di bagian atas dan bawah gambar. Sekarang Anda diundang untuk mengambil, berdasarkan kode yang diperbarui dari komponen MemeGenerator diperlihatkan di bawah ini, yang berbeda dari kode di atas dari komponen ini di mana formulir kosong ditambahkan di sini, untuk membuat beberapa bidang teks, topText dan bottomText . Perlu diingat bahwa komponen ini harus dikelola. Tambahkan atribut yang diperlukan padanya. Buat event onChange bidang-bidang ini di mana Anda perlu memperbarui properti negara terkait saat Anda memasukkan teks di dalamnya.

 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 

Ngomong-ngomong, perhatikan fakta bahwa untuk memasukkan komentar dalam kode yang dikembalikan oleh metode render() , kami melampirkannya dalam kurung keriting untuk menunjukkan kepada sistem bahwa fragmen ini harus ditafsirkan sebagai kode JavaScript.

Inilah yang harus Anda dapatkan pada tahap pengerjaan aplikasi ini:

 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 

Sekarang halaman aplikasi akan terlihat seperti yang ditunjukkan di bawah ini.


Aplikasi di browser

Meskipun hanya bidang dengan teks bantuan yang ditampilkan, memasukkan data ke dalamnya tidak menyebabkan perubahan pada antarmuka. Untuk memverifikasi operasi mekanisme yang diterapkan di sini, Anda dapat menggunakan perintah console.log() .

Sekarang kami akan bekerja pada bagian aplikasi yang bertanggung jawab untuk menampilkan meme gambar. Ingatlah bahwa sekarang kami memiliki larik yang berisi informasi tentang gambar yang rencananya akan digunakan sebagai dasar meme. Aplikasi harus, dengan menekan tombol Gen , secara acak memilih gambar dari array ini dan membentuk meme.

Ini adalah kode yang diperbarui untuk komponen MemeGenerator . Di sini, dalam metode render() , di bawah kode uraian formulir, ada elemen <div> , yang mencakup elemen <img> yang menampilkan gambar, dan beberapa elemen <h2> yang menampilkan label. Elemen <div> dan <h2> dirancang menggunakan gaya yang kami tambahkan ke proyek pada awal pekerjaan.

 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 

Seperti apa aplikasi ini sekarang.


Aplikasi di browser

Perhatikan fakta bahwa gambar yang menginisialisasi keadaan ditampilkan di sini. Kami belum menggunakan gambar yang disimpan di allMemeImgs milik negara. Mari kita coba memasukkan sesuatu ke dalam bidang teks.


Aplikasi di browser

Seperti yang Anda lihat, subsistem aplikasi yang bertanggung jawab untuk bekerja dengan teks berfungsi seperti yang diharapkan. Sekarang tinggal memastikan bahwa dengan mengklik tombol Gen gambar acak dipilih dari array dengan data gambar dan dimuat ke elemen <img> , yang ada pada halaman di bawah bidang input teks.

Untuk melengkapi aplikasi dengan fitur ini - lakukan tugas berikut. Buat metode yang menyala ketika Anda mengklik tombol Gen Metode ini harus memilih salah satu gambar yang informasinya disimpan di properti allMemeImgs , dan kemudian melakukan tindakan yang memungkinkan Anda untuk menampilkan gambar ini di elemen <img> yang terletak di bawah bidang input teks. allMemeImgs bahwa allMemeImgs menyimpan array objek yang menggambarkan gambar, dan bahwa setiap objek dari array ini memiliki properti url .

Berikut adalah kode yang memberikan solusi untuk masalah ini:

 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 

Tombol Gen dapat ditetapkan sebagai pengendali event yang terjadi ketika Anda mengkliknya, seperti halnya dengan tombol lain. Namun, mengingat fakta bahwa tombol ini digunakan untuk mengirimkan formulir, akan lebih baik menggunakan onSubmit formulir. Dalam penangan ini, handleSubmit() , kami memanggil metode event.preventDefault() acara event.preventDefault() datang ke dalamnya untuk membatalkan prosedur event.preventDefault() formulir standar, di mana halaman tersebut dimuat ulang. Selanjutnya, kita mendapatkan nomor acak dalam rentang dari 0 hingga nilai yang sesuai dengan indeks elemen terakhir dari array allMemeImgs dan menggunakan nomor ini untuk merujuk ke elemen dengan indeks yang sesuai. Beralih ke elemen yang merupakan objek, kita mendapatkan properti url objek ini dan menulisnya ke properti state randomImg . Setelah itu, komponen dirender ulang dan tampilan halaman berubah.


Halaman aplikasi di browser

Proyek kursus selesai.

Ringkasan


Dalam pelajaran ini, Anda membuat aplikasi yang menggunakan apa yang Anda pelajari saat menguasai Bereaksi. Lain kali kita akan berbicara tentang mengembangkan aplikasi React modern dan mendiskusikan ide-ide proyek, implementasi yang dapat Anda praktikkan bekerja dengan React.

Pembaca yang budiman! Pernahkah Anda mengalami kesulitan saat menyelesaikan proyek kursus ini?

Source: https://habr.com/ru/post/id447136/


All Articles