Kami akan membuat game kecil selama tutorial ini. Anda mungkin tergoda untuk melewatkannya karena Anda tidak membuat game — tetapi berikan kesempatan. Teknik-teknik yang akan Anda pelajari dalam tutorial merupakan dasar untuk membangun aplikasi React apa pun, dan menguasainya akan memberi Anda pemahaman yang mendalam tentang React
Tip
Tutorial ini dirancang untuk orang yang lebih suka belajar sambil melakukan. Jika Anda lebih suka mempelajari konsep dari awal, lihat panduan langkah demi langkah kami. Anda mungkin menganggap tutorial ini dan panduan ini saling melengkapi
Tutorial ini dibagi menjadi beberapa bagian
- akan memberi Anda titik awal untuk mengikuti tutorial
- akan mengajari Anda dasar-dasar React. komponen, props, dan state
- akan mengajari Anda teknik yang paling umum dalam pengembangan React
- akan memberi Anda wawasan yang lebih dalam tentang kekuatan unik React
Anda tidak harus menyelesaikan semua bagian sekaligus untuk mendapatkan nilai dari tutorial ini. Cobalah untuk mencapai sejauh yang Anda bisa — meskipun hanya satu atau dua bagian
Apa yang Kita Bangun?
Dalam tutorial ini, kami akan menunjukkan cara membuat game tic-tac-toe interaktif dengan React
Anda dapat melihat apa yang akan kami bangun di sini. Hasil Akhir. Jika kode tidak masuk akal bagi Anda, atau jika Anda tidak terbiasa dengan sintaks kode, jangan khawatir. Tujuan dari tutorial ini adalah untuk membantu Anda memahami React dan sintaksnya
Kami menyarankan Anda memeriksa permainan tic-tac-toe sebelum melanjutkan tutorial. Salah satu fitur yang akan Anda perhatikan adalah adanya daftar bernomor di sebelah kanan papan permainan. Daftar ini memberi Anda riwayat semua gerakan yang telah terjadi dalam gim, dan diperbarui seiring berjalannya gim
Anda dapat menutup permainan tic-tac-toe setelah Anda terbiasa dengannya. Kami akan memulai dari template yang lebih sederhana dalam tutorial ini. Langkah kami selanjutnya adalah menyiapkan Anda agar Anda dapat mulai membuat game
Prasyarat
Kami akan berasumsi bahwa Anda memiliki pengetahuan tentang HTML dan JavaScript, tetapi Anda harus dapat mengikuti bahkan jika Anda berasal dari bahasa pemrograman yang berbeda. Kami juga akan berasumsi bahwa Anda terbiasa dengan konsep pemrograman seperti fungsi, objek, larik, dan pada tingkat yang lebih rendah, kelas
Jika Anda perlu meninjau JavaScript, sebaiknya baca panduan ini. Perhatikan bahwa kami juga menggunakan beberapa fitur dari ES6 — JavaScript versi terbaru. Dalam tutorial ini, kami menggunakan fungsi panah, kelas, pernyataan return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );4, dan return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );5. Anda dapat menggunakan untuk memeriksa untuk apa kode ES6 dikompilasi
Pengaturan untuk Tutorial
Ada dua cara untuk menyelesaikan tutorial ini. Anda dapat menulis kode di browser Anda, atau Anda dapat menyiapkan lingkungan pengembangan lokal di komputer Anda
Opsi Pengaturan 1. Tulis Kode di Browser
Ini adalah cara tercepat untuk memulai
Pertama, buka Kode Pemula ini di tab baru. Tab baru akan menampilkan papan permainan tic-tac-toe kosong dan kode React. Kami akan mengedit kode React dalam tutorial ini
Anda sekarang dapat melewati opsi pengaturan kedua, dan pergi ke bagian untuk mendapatkan gambaran umum tentang React
Opsi Pengaturan 2. Lingkungan Pembangunan Lokal
Ini sepenuhnya opsional dan tidak diperlukan untuk tutorial ini
Opsional. Petunjuk untuk mengikuti secara lokal menggunakan editor teks pilihan Anda
Penyiapan ini membutuhkan lebih banyak pekerjaan tetapi memungkinkan Anda menyelesaikan tutorial menggunakan editor pilihan Anda. Berikut langkah-langkah yang harus diikuti
- Pastikan Anda memiliki Node versi terbaru. js diinstal
- Ikuti untuk membuat proyek baru
npx create-react-app my-app
- Hapus semua file di folder return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );6 dari proyek baru
Catatan
Jangan hapus seluruh folder return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );_7, hanya file sumber asli di dalamnya. Kami akan mengganti file sumber default dengan contoh untuk proyek ini di langkah berikutnya
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..
- Tambahkan file bernama return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );_8 di folder return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );6 dengan kode CSS ini
- Tambahkan file bernama class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }0 di folder return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );6 dengan kode JS ini
- Tambahkan tiga baris ini ke bagian atas class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }_0 di folder return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );6
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';
Sekarang jika Anda menjalankan class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }4 di folder proyek dan membuka class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }5 di browser, Anda akan melihat bidang tic-tac-toe kosong
Kami merekomendasikan mengikuti petunjuk ini untuk mengonfigurasi penyorotan sintaks untuk editor Anda
Tolong, saya Terjebak
Jika Anda buntu, periksa sumber daya dukungan komunitas. Secara khusus, Obrolan Reactilux adalah cara yang bagus untuk mendapatkan bantuan dengan cepat. Jika Anda tidak menerima jawaban, atau jika Anda tetap buntu, ajukan masalah, dan kami akan membantu Anda
Ringkasan
Sekarang setelah Anda siap, mari dapatkan ikhtisar tentang React
Apa itu Bereaksi?
React adalah pustaka JavaScript yang deklaratif, efisien, dan fleksibel untuk membangun antarmuka pengguna. Ini memungkinkan Anda membuat UI kompleks dari potongan kode kecil dan terisolasi yang disebut "komponen"
React memiliki beberapa jenis komponen, tetapi kita akan mulai dengan class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }6 subkelas
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />
Kami akan segera membahas tag mirip XML yang lucu. Kami menggunakan komponen untuk memberi tahu React apa yang ingin kami lihat di layar. Saat data kita berubah, React akan memperbarui dan merender ulang komponen kita secara efisien
Di sini, ShoppingList adalah kelas komponen React, atau tipe komponen React. Komponen mengambil parameter, disebut class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }_7 (singkatan dari "properti"), dan mengembalikan hierarki tampilan untuk ditampilkan melalui metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8
Metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 mengembalikan deskripsi tentang apa yang ingin Anda lihat di layar. React mengambil deskripsi dan menampilkan hasilnya. Secara khusus, class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }_8 mengembalikan elemen React, yang merupakan deskripsi ringan tentang apa yang akan dirender. Sebagian besar pengembang React menggunakan sintaks khusus yang disebut "JSX" yang membuat struktur ini lebih mudah untuk ditulis. Sintaks class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }1 diubah pada waktu pembuatan menjadi class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }2. Contoh di atas setara dengan
return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );
Jika Anda penasaran, class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }_3 dijelaskan lebih detail di , tetapi kami tidak akan menggunakannya dalam tutorial ini. Sebagai gantinya, kami akan tetap menggunakan JSX
JSX hadir dengan kekuatan penuh JavaScript. Anda dapat menempatkan ekspresi JavaScript apa pun di dalam kurung kurawal di dalam JSX. Setiap elemen React adalah objek JavaScript yang dapat Anda simpan dalam variabel atau bagikan dalam program Anda
Komponen class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }_4 di atas hanya merender komponen DOM bawaan seperti class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }1 dan class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }6. Tapi Anda juga bisa membuat dan merender komponen React kustom. Misalnya, kita sekarang dapat merujuk ke seluruh daftar belanja dengan menulis class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }7. Setiap komponen React dienkapsulasi dan dapat beroperasi secara independen;
Memeriksa Kode Pemula
Jika Anda akan mengerjakan tutorial di browser Anda, buka kode ini di tab baru. Kode Pemula. Jika Anda akan mengerjakan tutorial secara lokal, buka class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }8 di folder proyek Anda (Anda telah menyentuh file ini selama )
Kode Pemula ini adalah dasar dari apa yang kami buat. Kami telah menyediakan gaya CSS sehingga Anda hanya perlu fokus mempelajari React dan memprogram game tic-tac-toe
Dengan memeriksa kodenya, Anda akan melihat bahwa kami memiliki tiga komponen React
- Persegi
- Papan
- Permainan
Komponen Kotak membuat class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9 tunggal dan Papan membuat 9 kotak. Komponen Game merender papan dengan nilai placeholder yang akan kita ubah nanti. Saat ini tidak ada komponen interaktif
Melewati Data Melalui Alat Peraga
Agar kaki kita basah, mari kita coba meneruskan beberapa data dari komponen Board kita ke komponen Square kita
Kami sangat menyarankan mengetik kode dengan tangan saat Anda mengerjakan tutorial dan tidak menggunakan copy/paste. Ini akan membantu Anda mengembangkan memori otot dan pemahaman yang lebih kuat
Dalam metode class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }0 Board, ubah kode untuk meneruskan prop yang disebut class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }1 ke Square
class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }_
Ubah metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }_8 Square untuk menunjukkan nilai tersebut dengan mengganti class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }3 dengan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }4
class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }
Sebelum
Setelah. Anda akan melihat angka di setiap kotak dalam output yang diberikan
Lihat kode lengkapnya pada saat ini
Selamat. Anda baru saja "menyerahkan prop" dari komponen Board induk ke komponen Square anak. Meneruskan props adalah bagaimana informasi mengalir di aplikasi React, dari orang tua ke anak
Membuat Komponen Interaktif
Mari isi komponen Kotak dengan "X" saat kita mengkliknya. Pertama, ubah tag tombol yang dikembalikan dari fungsi class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }5 komponen Square menjadi ini
class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }
Jika Anda mengklik Kotak sekarang, Anda akan melihat 'klik' di konsol devtools browser Anda
Catatan
Untuk menyimpan pengetikan dan menghindari perilaku membingungkan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }6, kami akan menggunakan sintaks fungsi panah untuk penangan acara di sini dan selanjutnya di bawah
class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }
Perhatikan bagaimana dengan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_7, kami meneruskan fungsi sebagai prop class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8. Bereaksi hanya akan memanggil fungsi ini setelah klik. Melupakan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }9 dan menulis class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }0 adalah kesalahan umum, dan akan diaktifkan setiap kali komponen dirender ulang
Sebagai langkah selanjutnya, kami ingin komponen Kotak "mengingat" bahwa komponen itu diklik, dan mengisinya dengan tanda "X". Untuk "mengingat" sesuatu, komponen menggunakan status
Bereaksi komponen dapat memiliki status dengan menyetel class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }1 di konstruktornya. class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }_1 harus dianggap sebagai pribadi untuk komponen React yang didefinisikan di dalamnya. Mari simpan nilai Kotak saat ini di class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }1, dan ubah saat Kotak diklik
Pertama, kami akan menambahkan konstruktor ke kelas untuk menginisialisasi status
class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }
Catatan
Di kelas JavaScript, Anda harus selalu memanggil class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }4 saat menentukan konstruktor subkelas. Semua kelas komponen React yang memiliki class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }5 harus dimulai dengan panggilan class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }6
Sekarang kita akan mengubah metode ________8______8 Square untuk menampilkan nilai keadaan saat ini saat diklik
- Ganti class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }8 dengan class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }9 di dalam tag class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9
- Ganti event handler class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }1 dengan class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }2
- Letakkan class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }3 dan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 alat peraga pada baris terpisah untuk keterbacaan yang lebih baik
Setelah perubahan ini, tag class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9 yang dikembalikan oleh metode Square class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 terlihat seperti ini
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..0
Dengan memanggil class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }7 dari handler class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 dalam metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 Square, kita memberi tahu React untuk merender ulang Square itu setiap kali class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9 diklik. Setelah pembaruan, class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }_9 Square akan menjadi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..02, jadi kita akan melihat cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..03 di papan permainan. Jika Anda mengeklik Kotak mana pun, cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._03 akan muncul
Saat Anda memanggil cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..05 dalam sebuah komponen, React juga secara otomatis memperbarui komponen anak di dalamnya
Lihat kode lengkapnya pada saat ini
Alat pengembang
Ekstensi React Devtools untuk Chrome dan Firefox memungkinkan Anda memeriksa pohon komponen React dengan alat pengembang browser Anda
React DevTools memungkinkan Anda memeriksa properti dan status komponen React Anda
Setelah menginstal React DevTools, Anda dapat mengeklik kanan elemen apa pun di halaman, klik "Periksa" untuk membuka alat pengembang, dan tab React ("⚛️ Komponen" dan "⚛️ Profiler") akan muncul sebagai tab terakhir ke . Gunakan “⚛️ Komponen” untuk memeriksa pohon komponen
Namun, perhatikan ada beberapa langkah tambahan untuk membuatnya berfungsi dengan CodePen
- Masuk atau daftar dan konfirmasi email Anda (diperlukan untuk mencegah spam)
- Klik tombol "Garpu".
- Klik "Ubah Tampilan" dan kemudian pilih "Mode debug"
- Di tab baru yang terbuka, devtools seharusnya sudah memiliki tab React
Menyelesaikan Permainan
Kami sekarang memiliki blok bangunan dasar untuk permainan tic-tac-toe kami. Untuk memiliki permainan yang lengkap, sekarang kita perlu menempatkan "X" dan "O" secara bergantian di papan, dan kita memerlukan cara untuk menentukan pemenang
Mengangkat Status
Saat ini, setiap komponen Kotak mempertahankan status permainan. Untuk memeriksa pemenang, kami akan mempertahankan nilai masing-masing dari 9 kotak di satu lokasi
Kami mungkin berpikir bahwa Dewan seharusnya hanya meminta setiap Kotak untuk status Kotak. Meskipun pendekatan ini dimungkinkan di React, kami tidak menyarankannya karena kodenya menjadi sulit dipahami, rentan terhadap bug, dan sulit untuk di-refactor. Alih-alih, pendekatan terbaik adalah menyimpan status game di komponen Papan induk alih-alih di setiap Kotak. Komponen Papan dapat memberi tahu setiap Kotak apa yang harus ditampilkan dengan memberikan penyangga,
Untuk mengumpulkan data dari beberapa turunan, atau agar dua komponen turunan saling berkomunikasi, Anda perlu mendeklarasikan status bersama di komponen induknya. Komponen induk dapat meneruskan status kembali ke anak-anak dengan menggunakan alat peraga;
Mengangkat status ke dalam komponen induk adalah hal biasa ketika komponen React difaktorkan ulang — mari gunakan kesempatan ini untuk mencobanya
Tambahkan konstruktor ke Papan dan atur status awal Papan agar berisi larik 9 nol yang sesuai dengan 9 kotak
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..1
Saat kita mengisi papan nanti, larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..06 akan terlihat seperti ini
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..2
Metode Dewan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_0 saat ini terlihat seperti ini
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._3
Pada awalnya, kami dari Papan menunjukkan angka dari 0 hingga 8 di setiap Kotak. Pada langkah sebelumnya yang berbeda, kami mengganti angka dengan tanda “X”. Inilah mengapa Square saat ini mengabaikan prop class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }1 yang diteruskan oleh Dewan
Kami sekarang akan menggunakan mekanisme prop passing lagi. Kami akan memodifikasi Papan untuk menginstruksikan setiap Kotak individu tentang nilainya saat ini (cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..02, cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..11, atau cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..12). Kami telah mendefinisikan array cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 di konstruktor Board, dan kami akan memodifikasi metode class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }0 Board untuk membacanya
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._4
Lihat kode lengkapnya pada saat ini
Setiap Kotak sekarang akan menerima penyangga class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_1 yang akan menjadi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..02, cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..11, atau cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..12 untuk kotak kosong
Selanjutnya, kita perlu mengubah apa yang terjadi saat Kotak diklik. Komponen Dewan sekarang mempertahankan kotak mana yang diisi. Kita perlu membuat cara agar Square memperbarui status Dewan. Karena status dianggap pribadi untuk komponen yang mendefinisikannya, kami tidak dapat memperbarui status Dewan secara langsung dari Kotak
Sebagai gantinya, kami akan meneruskan fungsi dari Papan ke Kotak, dan kami akan membuat Kotak memanggil fungsi tersebut saat kotak diklik. Kami akan mengubah metode class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_0 di Board menjadi
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..5
Catatan
Kami membagi elemen yang dikembalikan menjadi beberapa baris agar mudah dibaca, dan menambahkan tanda kurung sehingga JavaScript tidak menyisipkan titik koma setelah cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..20 dan merusak kode kami
Sekarang kami memberikan dua properti dari Board ke Square. class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }1 dan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8. Prop class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_8 adalah fungsi yang dapat dipanggil Square saat diklik. Kami akan membuat perubahan berikut pada Kotak
- Ganti class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }_9 dengan class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }8 dalam metode Square class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8
- Ganti cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._27 dengan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..28 dalam metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 Square
- Hapus class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }_5 dari Kotak karena Kotak tidak lagi melacak status permainan
Setelah perubahan ini, komponen Kotak terlihat seperti ini
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._6
Saat Kotak diklik, fungsi class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 yang disediakan oleh Papan akan dipanggil. Berikut ulasan tentang bagaimana hal ini dicapai
- Prop class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_8 pada komponen DOM class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9 bawaan memberi tahu React untuk menyiapkan click event listener
- Saat tombol diklik, React akan memanggil event handler class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 yang didefinisikan dalam metode class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }5 Square
- Event handler ini memanggil cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._28. Prop class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }_8 Square ditentukan oleh Dewan
- Karena Papan melewati cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..38 ke Kotak, Kotak memanggil cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..39 Papan saat diklik
- Kami belum mendefinisikan metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._40, jadi kode kami mogok. Jika Anda mengeklik kotak sekarang, Anda akan melihat layar kesalahan berwarna merah yang mengatakan sesuatu seperti “ini. handleClick bukan fungsi”
Catatan
Atribut class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9 elemen DOM class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 memiliki arti khusus untuk Bereaksi karena merupakan komponen bawaan. Untuk komponen khusus seperti Kotak, penamaannya terserah Anda. Kita dapat memberi nama apa saja pada prop class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 Square atau metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..44 milik Dewan, dan kodenya akan bekerja sama. Di React, menggunakan nama cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..45 untuk props yang mewakili event dan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..46 untuk metode yang menangani event adalah hal yang konvensional.
Saat kami mencoba mengklik Kotak, kami akan mendapatkan kesalahan karena kami belum menentukan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..44. Kami sekarang akan menambahkan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._44 ke kelas Dewan
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._7
Lihat kode lengkapnya pada saat ini
Setelah perubahan ini, kami kembali dapat mengklik Kotak untuk mengisinya, sama seperti sebelumnya. Namun, sekarang status disimpan dalam komponen Board, bukan di komponen Square individual. Saat status Papan berubah, komponen Kotak akan dirender ulang secara otomatis. Menjaga status semua kotak di komponen Papan akan memungkinkannya menentukan pemenang di masa mendatang
Karena komponen Kotak tidak lagi mempertahankan keadaan, komponen Kotak menerima nilai dari komponen Papan dan menginformasikan komponen Papan saat diklik. Dalam istilah React, komponen Square sekarang adalah komponen yang dikontrol. Dewan memiliki kendali penuh atas mereka
Perhatikan bagaimana di cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._44, kami memanggil cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..50 untuk membuat salinan larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 untuk diubah alih-alih memodifikasi larik yang ada. Kami akan menjelaskan mengapa kami membuat salinan larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 di bagian berikutnya
Mengapa Kekekalan Itu Penting
Dalam contoh kode sebelumnya, kami menyarankan agar Anda membuat salinan larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 menggunakan metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..54 alih-alih memodifikasi larik yang ada. Sekarang kita akan membahas kekekalan dan mengapa kekekalan penting untuk dipelajari
Biasanya ada dua pendekatan untuk mengubah data. Pendekatan pertama adalah memutasi data dengan langsung mengubah nilai data. Pendekatan kedua adalah mengganti data dengan salinan baru yang memiliki perubahan yang diinginkan
Perubahan Data dengan Mutasi
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._8
Perubahan Data Tanpa Mutasi
cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._9
Hasil akhirnya sama tetapi dengan tidak memutasikan (atau mengubah data yang mendasarinya) secara langsung, kita mendapatkan beberapa keuntungan yang dijelaskan di bawah ini
Fitur Kompleks Menjadi Sederhana
Kekekalan membuat fitur kompleks lebih mudah diimplementasikan. Nanti dalam tutorial ini, kami akan menerapkan fitur "perjalanan waktu" yang memungkinkan kami meninjau riwayat permainan tic-tac-toe dan "melompat kembali" ke gerakan sebelumnya. Fungsionalitas ini tidak khusus untuk game — kemampuan untuk membatalkan dan mengulangi tindakan tertentu merupakan persyaratan umum dalam aplikasi. Menghindari mutasi data langsung memungkinkan kami menjaga versi riwayat game sebelumnya tetap utuh, dan menggunakannya kembali nanti
Mendeteksi Perubahan
Mendeteksi perubahan pada objek yang bisa berubah itu sulit karena dimodifikasi secara langsung. Deteksi ini membutuhkan objek yang dapat diubah untuk dibandingkan dengan salinan dirinya sendiri sebelumnya dan seluruh pohon objek untuk dilalui
Mendeteksi perubahan pada objek yang tidak dapat diubah jauh lebih mudah. Jika objek tetap yang direferensikan berbeda dari yang sebelumnya, maka objek tersebut telah berubah
Menentukan Kapan Re-Render di React
Manfaat utama kekekalan adalah membantu Anda membuat komponen murni di React. Data yang tidak dapat diubah dapat dengan mudah menentukan apakah perubahan telah dilakukan, yang membantu menentukan kapan suatu komponen perlu dirender ulang
Anda dapat mempelajari lebih lanjut tentang cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..55 dan bagaimana Anda dapat membuat komponen murni dengan membaca
Komponen Fungsi
Kami sekarang akan mengubah Kotak menjadi komponen fungsi
Di React, komponen fungsi adalah cara yang lebih sederhana untuk menulis komponen yang hanya berisi metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 dan tidak memiliki statusnya sendiri. Alih-alih mendefinisikan kelas yang memperluas class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }6, kita dapat menulis fungsi yang mengambil class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }7 sebagai input dan mengembalikan apa yang harus dirender. Komponen fungsi tidak terlalu membosankan untuk ditulis dibandingkan kelas, dan banyak komponen dapat diekspresikan dengan cara ini
Ganti kelas Square dengan fungsi ini
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';0
Kami telah mengubah cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..59 menjadi class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }7 kedua kali muncul
Lihat kode lengkapnya pada saat ini
Catatan
Saat kami memodifikasi Kotak menjadi komponen fungsi, kami juga mengubah cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..61 menjadi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..62 yang lebih pendek (perhatikan kurangnya tanda kurung di kedua sisi)
Bergiliran
Kami sekarang perlu memperbaiki cacat yang jelas dalam permainan tic-tac-toe kami. huruf “O” tidak dapat ditandai di papan tulis
Kami akan menetapkan langkah pertama menjadi "X" secara default. Kita dapat menyetel default ini dengan memodifikasi status awal di konstruktor Board kita
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';1
Setiap kali pemain bergerak, cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._63 (boolean) akan dibalik untuk menentukan pemain mana yang pergi berikutnya dan status permainan akan disimpan. Kami akan memperbarui fungsi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._44 Dewan untuk membalikkan nilai cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..63
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';2
Dengan perubahan ini, “X” dan “O” dapat bergiliran. Cobalah
Mari kita juga mengubah teks "status" di Board class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 sehingga menampilkan pemain mana yang mendapat giliran berikutnya
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';3
Setelah menerapkan perubahan ini, Anda akan memiliki komponen Board ini
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';4
Lihat kode lengkapnya pada saat ini
Menyatakan Pemenang
Sekarang kami menunjukkan giliran pemain mana yang berikutnya, kami juga harus menunjukkan kapan permainan dimenangkan dan tidak ada lagi giliran yang harus dilakukan. Salin fungsi pembantu ini dan tempel di akhir file
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';5
Diberikan array 9 kotak, fungsi ini akan memeriksa pemenang dan mengembalikan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..02, cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..11, atau cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..12 sebagaimana mestinya
Kami akan memanggil cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._70 di fungsi Dewan class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 untuk memeriksa apakah seorang pemain telah menang. Jika seorang pemain menang, kami dapat menampilkan teks seperti “Pemenang. X” atau “Pemenang. HAI". Kami akan mengganti deklarasi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..72 dalam fungsi class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 Dewan dengan kode ini
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';6
Kami sekarang dapat mengubah fungsi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._44 Papan untuk kembali lebih awal dengan mengabaikan klik jika seseorang telah memenangkan permainan atau jika Kotak sudah terisi
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';7
Lihat kode lengkapnya pada saat ini
Selamat. Anda sekarang memiliki permainan tic-tac-toe yang berfungsi. Dan Anda juga baru saja mempelajari dasar-dasar React. Jadi Anda mungkin adalah pemenang sebenarnya di sini
Menambahkan Perjalanan Waktu
Sebagai latihan terakhir, mari kita buat "kembali ke masa lalu" ke gerakan sebelumnya dalam permainan
Menyimpan Sejarah Gerakan
Jika kita mengubah larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._13, mengimplementasikan perjalanan waktu akan sangat sulit
Namun, kami menggunakan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..54 untuk membuat salinan baru dari larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 setelah setiap gerakan, dan. Ini akan memungkinkan kita untuk menyimpan setiap versi terakhir dari larik cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13, dan menavigasi di antara belokan yang telah terjadi
Kami akan menyimpan array cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._13 sebelumnya dalam array lain yang disebut cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80. Array cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._80 mewakili semua status papan, dari langkah pertama hingga terakhir, dan memiliki bentuk seperti ini
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';8
Sekarang kita perlu memutuskan komponen mana yang harus memiliki status cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80
Mengangkat Status, Lagi
Kami ingin komponen Game tingkat atas menampilkan daftar gerakan sebelumnya. Ini akan memerlukan akses ke cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._80 untuk melakukan itu, jadi kami akan menempatkan status cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80 di komponen Game tingkat atas
Menempatkan status cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._80 ke dalam komponen Game memungkinkan kita menghapus status cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 dari komponen Papan turunannya. Sama seperti kita dari komponen Kotak ke dalam komponen Papan, kita sekarang mengangkatnya dari Papan ke komponen Game tingkat atas. Ini memberi komponen Game kontrol penuh atas data Papan, dan memungkinkannya menginstruksikan Papan untuk membuat giliran sebelumnya dari cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80
Pertama, kita akan menyiapkan status awal untuk komponen Game di dalam konstruktornya
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_9
Selanjutnya, kita akan membuat komponen Board menerima cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..13 dan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 props dari komponen Game. Karena kita sekarang memiliki penangan klik tunggal di Papan untuk banyak Kotak, kita harus meneruskan lokasi setiap Kotak ke penangan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 untuk menunjukkan Kotak mana yang diklik. Berikut adalah langkah-langkah yang diperlukan untuk mengubah komponen Board
- Hapus class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }_5 di Papan
- Ganti cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._92 dengan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..93 di Dewan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }0
- Ganti cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._95 dengan cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..96 di Dewan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }0
Komponen Dewan sekarang terlihat seperti ini
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_0
Kami akan memperbarui fungsi ________8______8 komponen Game untuk menggunakan entri riwayat terbaru untuk menentukan dan menampilkan status game
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_1
Karena komponen Game sekarang merender status game, kami dapat menghapus kode yang sesuai dari metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 Dewan. Setelah pemfaktoran ulang, fungsi ________8______8 Dewan terlihat seperti ini
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_2
Terakhir, kita perlu memindahkan metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._44 dari komponen Board ke komponen Game. Kita juga perlu memodifikasi cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..44 karena status komponen Game disusun secara berbeda. Dalam metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..44 Game, kami menggabungkan entri riwayat baru ke cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_3
Catatan
Tidak seperti metode array import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';05 yang mungkin lebih Anda kenal, metode import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';06 tidak mengubah array asli, jadi kami lebih memilihnya
Pada titik ini, komponen Dewan hanya memerlukan metode class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }0 dan class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8. Status game dan metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._44 harus ada dalam komponen Game
Lihat kode lengkapnya pada saat ini
Menampilkan Gerakan Masa Lalu
Karena kami merekam sejarah permainan tic-tac-toe, sekarang kami dapat menampilkannya kepada pemain sebagai daftar gerakan sebelumnya
Kita telah mempelajari sebelumnya bahwa elemen React adalah objek JavaScript kelas satu; . Untuk merender beberapa item dalam React, kita dapat menggunakan larik elemen React
Dalam JavaScript, array memiliki metode import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_10 yang biasa digunakan untuk memetakan data ke data lain, misalnya
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_4
Dengan menggunakan metode import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_11, kita dapat memetakan riwayat perpindahan kita ke elemen React yang mewakili tombol di layar, dan menampilkan daftar tombol untuk "melompat" ke gerakan sebelumnya
Ayo import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';11 melalui cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80 dalam metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 Game
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_5
Lihat kode lengkapnya pada saat ini
Saat kita mengulangi array cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .._80, variabel import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';16 mengacu pada nilai elemen cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80 saat ini, dan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';18 merujuk pada indeks elemen cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80 saat ini. Kami hanya tertarik pada import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_18 di sini, karenanya import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';16 tidak ditugaskan untuk apa pun
Untuk setiap gerakan dalam riwayat permainan tic-tac-toe, kami membuat item daftar import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';22 yang berisi tombol class Square extends React.Component { render() { return ( <button className="square"> {this.props.value} </button> ); } }9. Tombol memiliki penangan class Square extends React.Component { render() { return ( <button className="square" onClick={function() { console.log('click'); }}> {this.props.value} </button> ); } }8 yang memanggil metode yang disebut import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';25. Kami belum menerapkan metode import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';26. Untuk saat ini, kita akan melihat daftar gerakan yang telah terjadi dalam game dan peringatan di konsol alat pengembang yang berbunyi
Peringatan. Setiap anak dalam larik atau iterator harus memiliki prop "kunci" yang unik. Periksa metode render "Game"
Mari kita bahas apa arti peringatan di atas
Memilih Kunci
Saat kita merender daftar, React menyimpan beberapa informasi tentang setiap item daftar yang dirender. Saat kami memperbarui daftar, React perlu menentukan apa yang telah berubah. Kami dapat menambahkan, menghapus, mengatur ulang, atau memperbarui item daftar
Bayangkan transisi dari
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_6
ke
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_7
Selain jumlah yang diperbarui, manusia yang membaca ini mungkin akan mengatakan bahwa kami menukar pesanan Alexa dan Ben dan memasukkan Claudia di antara Alexa dan Ben. Namun, Bereaksi adalah program komputer dan tidak tahu apa yang kami maksudkan. Karena React tidak dapat mengetahui maksud kita, kita perlu menentukan properti key untuk setiap item daftar untuk membedakan setiap item daftar dari saudara kandungnya. Salah satu opsi adalah menggunakan string import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';27, import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';28, import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';29. Jika kami menampilkan data dari database, ID database Alexa, Ben, dan Claudia dapat digunakan sebagai kunci
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_8
Ketika daftar dirender ulang, React mengambil kunci setiap item daftar dan mencari item daftar sebelumnya untuk kunci yang cocok. Jika daftar saat ini memiliki kunci yang sebelumnya tidak ada, React membuat sebuah komponen. Jika daftar saat ini kehilangan kunci yang ada di daftar sebelumnya, React akan menghapus komponen sebelumnya. Jika dua tombol cocok, komponen yang sesuai akan dipindahkan. Kunci memberi tahu React tentang identitas setiap komponen yang memungkinkan React mempertahankan status di antara render ulang. Jika kunci komponen berubah, komponen akan dihancurkan dan dibuat ulang dengan status baru
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';30 adalah properti khusus dan dicadangkan di React (bersama dengan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';31, fitur yang lebih canggih). Ketika sebuah elemen dibuat, React mengekstrak properti import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';30 dan menyimpan kunci langsung pada elemen yang dikembalikan. Meskipun import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_30 mungkin terlihat seperti milik class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }7, import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';30 tidak dapat dirujuk menggunakan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';36. Bereaksi secara otomatis menggunakan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_30 untuk memutuskan komponen mana yang akan diperbarui. Sebuah komponen tidak dapat menanyakan tentang ________12______30
Sangat disarankan agar Anda menetapkan kunci yang tepat setiap kali membuat daftar dinamis. Jika Anda tidak memiliki kunci yang sesuai, Anda mungkin ingin mempertimbangkan untuk merestrukturisasi data Anda sehingga Anda memilikinya
Jika tidak ada kunci yang ditentukan, React akan memberikan peringatan dan menggunakan indeks array sebagai kunci secara default. Menggunakan indeks array sebagai kunci bermasalah saat mencoba mengurutkan ulang item daftar atau memasukkan/menghapus item daftar. Melewati import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_39 secara eksplisit membungkam peringatan tetapi memiliki masalah yang sama dengan indeks array dan tidak direkomendasikan dalam banyak kasus
Kunci tidak harus unik secara global;
Menerapkan Perjalanan Waktu
Dalam sejarah permainan tic-tac-toe, setiap langkah sebelumnya memiliki ID unik yang terkait dengannya. itu adalah nomor urut dari langkah tersebut. Gerakan tidak pernah diurutkan ulang, dihapus, atau disisipkan di tengah, jadi aman menggunakan indeks gerakan sebagai kunci
Dalam metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 komponen Game, kita dapat menambahkan kunci sebagai import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';41 dan peringatan React tentang kunci akan hilang
class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // Example usage: <ShoppingList name="Mark" />_9
Lihat kode lengkapnya pada saat ini
Mengklik salah satu tombol item daftar menimbulkan kesalahan karena metode ________12______42 tidak ditentukan. Sebelum kami menerapkan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';42, kami akan menambahkan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';44 ke status komponen Game untuk menunjukkan langkah mana yang sedang kami lihat
Pertama, tambahkan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_45 ke status awal di class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }5 Game
return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );0
Selanjutnya, kita akan menentukan metode import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_42 di Game untuk memperbarui import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';44 itu. Kita juga menyetel cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..63 menjadi true jika angka yang kita ubah import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';44 menjadi genap
return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );_1
Pemberitahuan dalam metode import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_42, kami belum memperbarui cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..80 milik negara. Itu karena pembaruan status digabungkan atau dengan kata yang lebih sederhana React hanya akan memperbarui properti yang disebutkan dalam metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..05 meninggalkan status yang tersisa apa adanya. Untuk info lebih lanjut
Kami sekarang akan membuat beberapa perubahan pada metode cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd ..44 Game yang aktif saat Anda mengeklik kotak
Status import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_44 yang telah kami tambahkan mencerminkan langkah yang ditampilkan kepada pengguna sekarang. Setelah kita melakukan langkah baru, kita perlu memperbarui import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';44 dengan menambahkan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';57 sebagai bagian dari argumen class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }7. Ini memastikan kami tidak terjebak menunjukkan langkah yang sama setelah yang baru dibuat
Kami juga akan mengganti bacaan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';_59 dengan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';60. Ini memastikan bahwa jika kita "kembali ke masa lalu" dan kemudian mengambil langkah baru dari titik itu, kita membuang semua sejarah "masa depan" yang sekarang salah.
return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );_2
Terakhir, kami akan mengubah metode class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }8 komponen Game dari selalu merender langkah terakhir menjadi merender langkah yang saat ini dipilih sesuai dengan import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css';44
return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* .. h1 children .. */), React.createElement('ul', /* .. ul children .. */) );_3
Jika kita mengklik salah satu langkah dalam riwayat permainan, papan tic-tac-toe akan segera diperbarui untuk menunjukkan tampilan papan setelah langkah tersebut terjadi
Lihat kode lengkapnya pada saat ini
Membungkus
Selamat. Anda telah membuat game tic-tac-toe itu
- Memungkinkan Anda bermain tic-tac-toe,
- Menunjukkan ketika seorang pemain telah memenangkan permainan,
- Menyimpan riwayat game saat game berlangsung,
- Mengizinkan pemain meninjau riwayat game dan melihat papan game versi sebelumnya
Kerja bagus. Kami harap Anda sekarang merasa memiliki pemahaman yang baik tentang cara kerja React
Lihat hasil akhirnya di sini. Hasil Akhir
Jika Anda memiliki waktu ekstra atau ingin melatih keterampilan Bereaksi baru Anda, berikut adalah beberapa ide untuk peningkatan yang dapat Anda lakukan pada permainan tic-tac-toe yang dicantumkan dalam urutan kesulitan yang meningkat
- Tampilkan lokasi untuk setiap perpindahan dalam format (kolom, baris) di daftar riwayat perpindahan
- Tebalkan item yang saat ini dipilih dalam daftar pemindahan
- Tulis ulang Papan untuk menggunakan dua loop untuk membuat kotak alih-alih melakukan hardcoding
- Tambahkan tombol sakelar yang memungkinkan Anda mengurutkan gerakan dalam urutan naik atau turun
- Saat seseorang menang, sorot tiga kotak yang menyebabkan kemenangan
- Ketika tidak ada yang menang, tampilkan pesan tentang hasil seri
Sepanjang tutorial ini, kita menyentuh konsep React termasuk elemen, komponen, properti, dan status. Untuk penjelasan yang lebih mendetail tentang masing-masing topik ini, lihat dokumentasi lainnya. Untuk mempelajari lebih lanjut tentang mendefinisikan komponen, lihat referensi class Board extends React.Component { renderSquare(i) { return <Square value={i} />; } }6 API