Bekerja dengan React Context API

Diterbitkan: 2022-03-11

React Context API telah ada sebagai fitur eksperimental untuk sementara waktu sekarang, tetapi hanya dalam versi 16.3.0 React yang menjadi aman untuk digunakan dalam produksi. Artikel di bawah ini akan menunjukkan kepada Anda dua aplikasi toko web dasar, satu dibuat dengan API Konteks dan satu lagi tanpanya.

API baru ini memecahkan satu masalah utama – pengeboran prop . Bahkan jika Anda tidak terbiasa dengan istilah tersebut, jika Anda pernah bekerja pada aplikasi React.js, itu mungkin terjadi pada Anda. Pengeboran prop adalah pemrosesan mendapatkan data dari komponen A ke komponen Z dengan melewatkannya melalui beberapa lapisan komponen React perantara. Komponen akan menerima alat peraga secara tidak langsung dan Anda , Pengembang Bereaksi harus memastikan semuanya berjalan dengan baik.

Mari kita jelajahi bagaimana Anda akan menangani masalah umum tanpa React Context API,

aplikasi.js

 class App extends Component { state = { cars: { car001: { name: 'Honda', price: 100 }, car002: { name: 'BMW', price: 150 }, car003: { name: 'Mercedes', price: 200 } } }; incrementCarPrice = this.incrementCarPrice.bind(this); decrementCarPrice = this.decrementCarPrice.bind(this); incrementCarPrice(selectedID) { // a simple method that manipulates the state const cars = Object.assign({}, this.state.cars); cars[selectedID].price = cars[selectedID].price + 1; this.setState({ cars }); } decrementCarPrice(selectedID) { // a simple method that manipulates the state const cars = Object.assign({}, this.state.cars); cars[selectedID].price = cars[selectedID].price - 1; this.setState({ cars }); } render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to my web store</h1> </header> {/* Pass props twice */} <ProductList cars={this.state.cars} incrementCarPrice={this.incrementCarPrice} decrementCarPrice={this.decrementCarPrice} /> </div> ); } }

Daftar Produk .js

 const ProductList = props => ( <div className="product-list"> <h2>Product list:</h2> {/* Pass props twice */} <Cars cars={props.cars} incrementCarPrice={props.incrementCarPrice} decrementCarPrice={props.decrementCarPrice} /> {/* Other potential product categories which we will skip for this demo: */} {/* <Electronics /> */} {/* <Clothes /> */} {/* <Shoes /> */} </div> ); export default ProductList;

mobil.js

 const Cars = props => ( <Fragment> <h4>Cars:</h4> {/* Finally we can use data */} {Object.keys(props.cars).map(carID => ( <Car key={carID} name={props.cars[carID].name} price={props.cars[carID].price} incrementPrice={() => props.incrementCarPrice(carID)} decrementPrice={() => props.decrementCarPrice(carID)} /> ))} </Fragment> );

mobil.js

 const Cars = props => ( <Fragment> <p>Name: {props.name}</p> <p>Price: ${props.price}</p> <button onClick={props.incrementPrice}>&uarr;</button> <button onClick={props.decrementPrice}>&darr;</button> </Fragment> );

Memang, ini bukan cara terbaik untuk menangani data Anda, tapi saya harap ini menunjukkan mengapa pengeboran prop menyebalkan . Jadi bagaimana Context API membantu kita menghindari ini?

Memperkenalkan Toko Web Konteks

Mari kita memfaktorkan ulang aplikasi dan mendemonstrasikan apa yang dapat dilakukannya. Singkatnya, API Konteks memungkinkan Anda memiliki penyimpanan pusat tempat data Anda berada (ya, seperti di Redux). Toko dapat dimasukkan ke dalam komponen apa pun secara langsung. Anda dapat memotong perantara!

Contoh dua aliran status: satu dengan React Context API, dan satu tanpa

Pemfaktoran ulang cukup mudah – kita tidak perlu membuat perubahan apa pun pada struktur komponen. Kami memang perlu membuat beberapa komponen baru – penyedia dan konsumen.

1. Inisialisasi Konteks

Pertama, kita perlu membuat konteks, yang nantinya dapat kita gunakan untuk membuat penyedia dan konsumen.

MyContext.js

 import React from 'react'; // this is the equivalent to the createStore method of Redux // https://redux.js.org/api/createstore const MyContext = React.createContext(); export default MyContext;

2. Buat Penyedia

Setelah selesai, kita dapat mengimpor konteks dan menggunakannya untuk membuat penyedia kita, yang kita sebut MyProvider. Di dalamnya, kami menginisialisasi status dengan beberapa nilai, yang dapat Anda bagikan melalui value prop komponen penyedia kami. Dalam contoh kami, kami membagikan this.state.cars bersama dengan beberapa metode yang memanipulasi status. Pikirkan metode ini sebagai reduksi di Redux.

Penyedia Saya.js

 import MyContext from './MyContext'; class MyProvider extends Component { state = { cars: { car001: { name: 'Honda', price: 100 }, car002: { name: 'BMW', price: 150 }, car003: { name: 'Mercedes', price: 200 } } }; render() { return ( <MyContext.Provider value={{ cars: this.state.cars, incrementPrice: selectedID => { const cars = Object.assign({}, this.state.cars); cars[selectedID].price = cars[selectedID].price + 1; this.setState({ cars }); }, decrementPrice: selectedID => { const cars = Object.assign({}, this.state.cars); cars[selectedID].price = cars[selectedID].price - 1; this.setState({ cars }); } }} > {this.props.children} </MyContext.Provider> ); } }

Untuk membuat penyedia dapat diakses oleh komponen lain, kita perlu membungkus aplikasi kita dengannya (ya, seperti di Redux). Saat melakukannya, kita dapat menyingkirkan status dan metode karena sekarang sudah didefinisikan di MyProvider.js.

aplikasi.js

 class App extends Component { render() { return ( <MyProvider> <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to my web store</h1> </header> <ProductList /> </div> </MyProvider> ); } }

3. Buat Konsumen

Kita perlu mengimpor konteks lagi dan membungkus komponen kita dengannya yang menyuntikkan argumen konteks ke dalam komponen. Setelah itu, itu cukup lurus ke depan. Anda menggunakan konteks , dengan cara yang sama Anda menggunakan alat peraga . Ini menyimpan semua nilai yang telah kami bagikan di MyProducer, kami hanya perlu menggunakannya!

mobil.js

 const Cars = () => ( <MyContext.Consumer> {context => ( <Fragment> <h4>Cars:</h4> {Object.keys(context.cars).map(carID => ( <Car key={carID} name={context.cars[carID].name} price={context.cars[carID].price} incrementPrice={() => context.incrementPrice(carID)} decrementPrice={() => context.decrementPrice(carID)} /> ))} </Fragment> )} </MyContext.Consumer> );

Apa yang kita lupakan? Daftar Produk! Di sinilah manfaatnya terlihat. Kami tidak melewatkan data atau metode apa pun. Komponen disederhanakan karena hanya perlu merender beberapa komponen.

Daftar Produk.js

 const ProductList = () => ( <div className="product-list"> <h2>Product list:</h2> <Cars /> {/* Other potential product categories which we will skip for this demo: */} {/* <Electronics /> */} {/* <Clothes /> */} {/* <Shoes /> */} </div> );

Selama artikel ini, saya membuat beberapa perbandingan antara Redux dan Context API. Salah satu keuntungan terbesar Redux adalah fakta bahwa aplikasi Anda dapat memiliki toko pusat yang dapat diakses dari komponen apa pun. Dengan API Konteks baru, Anda memiliki fungsi itu secara default. Banyak hype telah dibuat bahwa Context API akan membuat Redux menjadi usang.

Ini mungkin benar bagi Anda yang hanya menggunakan Redux untuk kemampuan toko pusatnya. Jika itu satu-satunya fitur yang Anda gunakan untuk itu, Anda sekarang dapat menggantinya dengan API Konteks dan menghindari pengeboran penyangga tanpa menggunakan perpustakaan pihak ketiga.

Jika Anda tertarik untuk mengukur dan mengoptimalkan kinerja aplikasi React Anda, baca Panduan untuk Mengoptimalkan Kinerja React oleh sesama Toptaler William Wang.