Pengantar Context API React

Diterbitkan: 2022-03-10
Ringkasan cepat Dalam artikel ini, Anda akan mempelajari cara menggunakan React's Context API yang memungkinkan Anda mengelola status aplikasi global di aplikasi React Anda tanpa menggunakan pengeboran alat peraga.

Untuk 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 →

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

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:

  1. Metode pertama adalah melalui Class.contextType .

    Untuk menggunakan metode ini, kami menetapkan objek konteks dari ThemeContext kami ke properti contextType kelas kami. Setelah itu, kita akan dapat mengakses nilai konteks menggunakan this.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 menetapkan ThemeContext ke properti contextType dari kelas kita, saya menyimpan objek tema saat ini dalam variabel currentTheme .

    Sekarang, kita akan mengambil warna dari variabel currentTheme 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.
  2. 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 komponen MainWithClass 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 dari ThemeContext kami yang kami alias sebagai "tema" dan kami mengambil nilai warna untuk mode tema itu dan menetapkannya ke variabel currentTheme . 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

  1. Versi komponen MainWithClass yang menggunakan metode Class.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> ); } }
  2. Versi komponen MainWithClass yang menggunakan metode ThemeContext.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