Pengantar Context API React
Diterbitkan: 2022-03-10Untuk tutorial ini, Anda harus memiliki pemahaman yang adil tentang hook. Namun, sebelum kita mulai, saya akan membahas secara singkat apa itu hook dan hook yang akan kita gunakan dalam artikel ini.
Menurut Dokumen Bereaksi:
“ Hooks adalah tambahan baru di React 16.8. Mereka memungkinkan Anda menggunakan status dan fitur React lainnya tanpa menulis kelas.”
Itu pada dasarnya apa itu React hook. Ini memungkinkan kita untuk menggunakan status, referensi, dan fitur React lainnya di komponen fungsional kita.
Mari kita bahas dua kait yang akan kita temui di artikel ini.
useState
Keadaan Penggunaan
Kait useState memungkinkan kita untuk menggunakan status dalam komponen fungsional kita. Kait useState
mengambil nilai awal status kita sebagai satu-satunya argumen, dan mengembalikan array dua elemen. Elemen pertama adalah variabel status kita dan elemen kedua adalah fungsi di mana kita dapat menggunakan pembaruan nilai variabel status.
Mari kita lihat contoh berikut:
import React, {useState} from "react"; function SampleComponent(){ const [count, setCount] = useState(0); }
Di sini, count
adalah variabel status kita dan nilai awalnya adalah 0
sedangkan setCount
adalah fungsi yang dapat kita gunakan untuk memperbarui nilai count.
useContext
Saya akan membahas ini nanti di artikel tetapi kait ini pada dasarnya memungkinkan kita untuk mengkonsumsi nilai dari suatu konteks. Apa artinya ini sebenarnya akan menjadi lebih jelas nanti di artikel.
Ruang Kerja Benang
Ruang kerja benang memungkinkan Anda mengatur basis kode proyek Anda menggunakan repositori monolitik (monorepo). Bereaksi adalah contoh yang baik dari proyek sumber terbuka yang monorepo dan menggunakan ruang kerja Yarn untuk mencapai tujuan itu. Baca artikel terkait →
Mengapa Kita Membutuhkan Context API?
Kami ingin membangun komponen "pengalih tema" yang beralih antara mode terang dan mode gelap untuk aplikasi React kami. Setiap komponen harus memiliki akses ke mode tema saat ini sehingga mereka dapat ditata sesuai dengan itu.
Biasanya, kami akan menyediakan mode tema saat ini ke semua komponen melalui alat peraga dan memperbarui tema saat ini menggunakan state
:
import React from "react"; import ReactDOM from "react-dom"; function App() { return ( <div> <Text theme= "blue" /> <h1>{theme}</h1> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
Dalam contoh kode di atas, kami membuat Komponen Teks yang merender elemen h1
. Warna elemen h1
tergantung pada mode tema saat ini. Saat ini, temanya adalah biru. Kita dapat beralih antara tema blue
dan red
dengan menggunakan state
.
Kami akan membuat status yang disebut "tema" menggunakan kait useState
. Kait useState
akan mengembalikan nilai tema saat ini dan fungsi yang dapat kita gunakan untuk memperbarui tema.
Jadi, mari kita buat status tema kita:
const [theme, setTheme] = React.useState("blue");
Kami juga akan menambahkan elemen tombol ke komponen App
kami. Tombol ini akan digunakan untuk mengganti tema dan membutuhkan event handler klik. Jadi, mari kita tulis event handler klik seperti ini:
const onClickHandler = () => { setTheme(); }
Sekarang, kami ingin mengatur tema baru ke Red
jika tema saat ini Blue
, dan sebaliknya. Daripada menggunakan pernyataan if
, cara yang lebih nyaman untuk melakukannya adalah dengan bantuan operator ternary di JavaScript.
setTheme( theme === "red"? "blue": "red");
Jadi sekarang, kami telah menulis handler onClick
kami. Mari tambahkan elemen tombol ini ke komponen App
:
<button onClick = {onClickHandler}>Change theme</button>
Mari kita juga mengubah nilai props tema dari komponen Text ke status tema.
<Text theme={theme}/>
Sekarang, kita harus memiliki ini:
import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function App() { const[theme, setTheme] = React.useState("red"); const onClickHandler = () => { setTheme( theme === "red"? "blue": "red"); } return ( <div> <Text theme={theme}/> <button onClick = {onClickHandler}>Change theme</button> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
Kami sekarang dapat beralih di antara dua tema kami. Namun, jika ini adalah aplikasi yang jauh lebih besar, akan sulit untuk menggunakan tema dalam komponen yang sangat bersarang dan kode menjadi berat.
Memperkenalkan API Konteks
Izinkan saya memperkenalkan API Konteks. Menurut dokumentasi Bereaksi:
“Konteks menyediakan cara untuk melewatkan data melalui pohon komponen tanpa harus menurunkan props secara manual di setiap level.”
Untuk definisi yang lebih mendalam, ini menyediakan cara bagi Anda untuk membuat data tertentu tersedia untuk semua komponen di seluruh pohon komponen tidak peduli seberapa dalam komponen itu mungkin bersarang.
Mari kita lihat contoh ini:
const App = () => { return( <ParentComponent theme = "light"/> ); } const ParentComponent = (props) => ( <Child theme = {props.theme} /> ) const Child = (props) => ( <Grandchild theme = {props.theme} /> ) const Grandchild = (props) => ( <p>Theme: {props.theme}</p> )
Dalam contoh di atas, kami menetapkan tema aplikasi menggunakan alat peraga di ParentComponent
yang disebut theme
. Kami harus meneruskan alat peraga itu ke semua komponen ke bawah pohon komponen untuk mendapatkannya di tempat yang dibutuhkan yaitu komponen GrandChild
. ChildComponent
tidak ada hubungannya dengan alat peraga tema tetapi hanya digunakan sebagai perantara.
Sekarang, bayangkan komponen GrandChild
bersarang lebih dalam daripada di contoh teratas. Kami harus melewati alat peraga tema dengan cara yang sama seperti yang kami lakukan di sini yang akan merepotkan. Ini adalah masalah yang dipecahkan oleh Context
. Dengan Context
, setiap komponen di pohon komponen memiliki akses ke data apa pun yang kami putuskan untuk dimasukkan ke dalam konteks kami.
Mari Mulai Dengan Context
Saatnya untuk mereplikasi tombol pengalih tema yang kami buat di awal artikel dengan API Konteks. Kali ini, pengalih tema kita akan menjadi komponen yang terpisah. Kami akan membangun komponen ThemeToggler
yang mengganti tema aplikasi React kami menggunakan Context
.
Pertama, mari kita inisialisasi aplikasi React kita. (Saya lebih suka menggunakan create-react-app
tetapi Anda dapat menggunakan metode apa pun yang Anda inginkan.)
Setelah Anda menginisialisasi proyek React Anda, buat file bernama ThemeContext.js di folder /src
Anda. Anda juga dapat membuat folder bernama /context
dan menempatkan file ThemeContext Anda di sana jika Anda mau.
Sekarang, mari kita lanjutkan.
Membuat API Konteks Anda
Kami akan membuat konteks tema kami di file ThemeContext.js kami.
Untuk membuat konteks, kita menggunakan React.createContext
yang membuat objek konteks. Anda dapat memasukkan apa saja sebagai argumen ke React.createContext
. Dalam hal ini, kita akan meneruskan string yang merupakan mode tema saat ini. Jadi sekarang mode tema kami saat ini adalah mode tema "ringan".
import React from "react"; const ThemeContext = React.createContext("light"); export default ThemeContext;
Untuk membuat konteks ini tersedia untuk semua komponen React kami, kami harus menggunakan Provider. Apa itu Penyedia? Menurut dokumentasi React, setiap objek konteks dilengkapi dengan komponen Provider React yang memungkinkan komponen yang mengkonsumsi untuk berlangganan perubahan konteks. Ini adalah penyedia yang memungkinkan konteks untuk dikonsumsi oleh komponen lain. Yang mengatakan, mari kita buat penyedia kami.
Buka file App.js Anda. Untuk membuat penyedia kami, kami harus mengimpor ThemeContext
kami.
Setelah ThemeContext
telah diimpor, kita harus menyertakan konten komponen App
kita dalam tag ThemeContext.Provider
dan memberikan komponen ThemeContext.Provider
sebuah alat peraga yang disebut value
yang akan berisi data yang ingin kita sediakan untuk pohon komponen kita.
function App() { const theme = "light"; return ( <ThemeContext.Provider value = {theme}> <div> </div> </ThemeContext.Provider> ); }
Jadi sekarang nilai "ringan" tersedia untuk semua komponen kami (yang akan segera kami tulis).
Membuat File Tema Kami
Sekarang, kita akan membuat file tema kita yang akan berisi nilai warna yang berbeda untuk tema terang dan gelap kita. Buat file di folder /src
Anda bernama Colors.js .
Di Colors.js , kita akan membuat objek bernama AppTheme
. Objek ini akan berisi warna untuk tema kita. Setelah selesai, ekspor objek AppTheme
seperti:
const AppTheme = { light: { textColor: "#000", backgroundColor: "#fff" }, dark: { textColor: "#fff", backgroundColor: "#333" } } export default AppTheme;
Sekarang saatnya untuk mulai membuat komponen React kita yang berbeda.
Membuat Komponen React Kami
Mari kita buat komponen berikut:
-
Header
-
ThemeToggler
-
MainWithClass
Header.jsx
import React from "react"; import ThemeToggler from "./ThemeToggler"; const headerStyles = { padding: "1rem", display: "flex", justifyContent: "space-between", alignItems: "center" } const Header = () => { return( <header style = {headerStyles}> <h1>Context API</h1> <ThemeToggler /> </header> ); } export default Header;
ThemeToggler.jsx
(Untuk saat ini, kami hanya akan mengembalikan div
kosong.)
import React from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { return( <div style = {themeTogglerStyle}> </div> ); } export default ThemeToggler;
Mengkonsumsi Konteks Dengan Komponen Berbasis Kelas
Di sini, kita akan menggunakan nilai ThemeContext
kita. Seperti yang mungkin sudah Anda ketahui, kami memiliki dua metode penulisan komponen di React : melalui fungsi atau kelas. Proses penggunaan konteks di kedua metode berbeda sehingga kita akan membuat dua komponen untuk dijadikan bagian utama dari aplikasi kita: MainWithClass
dan MainWithFunction
.
Mari kita mulai dengan MainWithClass
.
MainWithClass.jsx
Kita harus mengimpor ThemeContext
dan AppTheme
. Setelah selesai, kami akan menulis kelas yang mengembalikan JSX kami dari metode render. Sekarang kita harus mengkonsumsi konteks kita. Ada dua metode untuk melakukan ini dengan komponen berbasis kelas:
- Metode pertama adalah melalui
Class.contextType
.
Untuk menggunakan metode ini, kami menetapkan objek konteks dariThemeContext
kami ke properticontextType
kelas kami. Setelah itu, kita akan dapat mengakses nilai konteks menggunakanthis.context
. Anda juga dapat merujuk ini di salah satu metode siklus hidup dan bahkan metode render.import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context]; return( <main></main> ); } }
Setelah menetapkanThemeContext
ke properticontextType
dari kelas kita, saya menyimpan objek tema saat ini dalam variabelcurrentTheme
.
Sekarang, kita akan mengambil warna dari variabelcurrentTheme
dan menggunakannya untuk menata beberapa markup.render() { const currentTheme = AppTheme[this.context]; return ( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main>
Itu dia! Namun, metode ini membatasi Anda untuk mengonsumsi hanya satu konteks. - Metode kedua adalah
ThemeContext.Consumer
yang melibatkan penggunaan Konsumen. Setiap objek konteks juga dilengkapi dengan komponen Consumer React yang dapat digunakan dalam komponen berbasis kelas. Komponen konsumen mengambil anak sebagai fungsi dan fungsi itu mengembalikan node React. Nilai konteks saat ini diteruskan ke fungsi itu sebagai argumen.
Sekarang, mari kita ganti kode di komponenMainWithClass
kita dengan ini:class Main extends Component { constructor() { super(); this.state = { } } render(){ return( <ThemeContext.Consumer> { (theme) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } }
Seperti yang Anda lihat, kami menggunakan nilai saat ini dariThemeContext
kami yang kami alias sebagai "tema" dan kami mengambil nilai warna untuk mode tema itu dan menetapkannya ke variabelcurrentTheme
. Dengan metode ini, Anda dapat menggunakan beberapa Konsumen.
Itulah dua metode mengkonsumsi konteks dengan komponen berbasis kelas.
Mengkonsumsi Konteks Dengan Komponen Fungsional
Mengkonsumsi konteks dengan komponen fungsional lebih mudah dan tidak membosankan daripada melakukannya dengan komponen berbasis kelas. Untuk menggunakan konteks dalam komponen fungsional, kita akan menggunakan pengait yang disebut useContext
.
Berikut adalah tampilan menggunakan ThemeContext
kami dengan komponen fungsional:
const Main = () => { const theme = useContext(ThemeContext); const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
Seperti yang Anda lihat, yang harus kami lakukan hanyalah menggunakan kait useContext
kami dengan ThemeContext
kami yang diteruskan sebagai argumen.
Catatan : Anda harus menggunakan komponen yang berbeda ini di file App.js untuk melihat hasilnya.
Memperbarui Tema Kami Dengan Komponen ThemeToggler
Sekarang kita akan bekerja pada komponen ThemeToggler
kita. Kita harus bisa beralih antara tema terang dan gelap. Untuk melakukan ini, kita perlu mengedit ThemeContext.js kita. React.createContext
kita sekarang akan mengambil objek yang menyerupai hasil dari hook useState
sebagai argumen.
const ThemeContext = React.createContext(["light", () => {}]);
Kami meneruskan sebuah array ke fungsi React.createContext
. Elemen pertama dalam array adalah mode tema saat ini dan elemen kedua adalah fungsi yang akan digunakan untuk memperbarui tema. Seperti yang saya katakan, ini hanya menyerupai hasil dari kait useState
tetapi itu bukan hasil dari kait useState
.
Sekarang kita akan mengedit file App.js kita. Kita perlu mengubah nilai yang diteruskan ke penyedia menjadi kait useState
. Sekarang nilai Konteks Tema kami adalah kait useState
yang nilai defaultnya adalah "ringan".
function App() { const themeHook = useState("light"); return ( <ThemeContext.Provider value = {themeHook}> <div> <Header /> <Main /> </div> </ThemeContext.Provider> ); }
Menulis Komponen ThemeToggler
Kami
Mari kita sekarang benar-benar menulis komponen ThemeToggler
kita:
import React,{useContext} from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { const[themeMode, setThemeMode] = useContext(ThemeContext); return( <div style = {themeTogglerStyle} onClick = {() => {setThemeMode(themeMode === "light"? "dark": "light")}}> <span title = "switch theme"> {themeMode === "light" ? "" : "️"} </span> </div> ); } export default ThemeToggler;
Karena nilai konteks tema kita sekarang menjadi pengait setiap kali kita memanggil useContext
di atasnya, itu akan mengembalikan sebuah array. Menggunakan destructuring, kami dapat mengambil elemen dari array. Kami kemudian menulis event handler onClick
untuk ThemeToggler
kami. Dengan kode itu, setiap kali pengalih tema diklik, itu akan mengganti tema aplikasi kita.
Sekarang kita akan mengedit versi yang berbeda dari komponen Main
kita.
Mengedit Komponen MainWithClass
Kami
- Versi komponen
MainWithClass
yang menggunakan metodeClass.contextType
:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context[0]]; return( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } }
- Versi komponen
MainWithClass
yang menggunakan metodeThemeContext.Consumer
:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component { constructor() { super(); this.state = {} } render() { return ( <ThemeContext.Consumer> { ([theme]) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } } export default Main;
Mengedit Komponen MainWithFunction
Kami
Komponen MainWithFunction
harus diedit sebagai berikut:
import React, { useContext } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; const Main = () => { const theme = useContext(ThemeContext)[0]; const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
Kesimpulan
Itu dia! Kami telah berhasil mengimplementasikan dua mode tema untuk aplikasi React kami menggunakan Context API.
Dalam prosesnya, kami telah belajar:
- Apa itu API Konteks dan masalah yang dipecahkannya;
- Kapan menggunakan API Konteks;
- Membuat
Context
dan menggunakannya dalam komponen fungsional dan berbasis kelas.
Bacaan Lebih Lanjut tentang SmashingMag:
- Styling Dalam Aplikasi Web Modern
- Membangun Aplikasi Seluler Dengan Ionic Dan React
- Bangun PWA Dengan Webpack Dan Workbox
- Mengenal MutationObserver API