Artikel, yang kami terbitkan hari ini, akan membahas cara membuat komponen kontainer dalam aplikasi Bereaksi yang terkait dengan keadaan Redux. Materi ini didasarkan pada deskripsi mekanisme manajemen negara dalam Bereaksi menggunakan paket
react-redux . Diasumsikan bahwa Anda sudah memiliki pemahaman dasar tentang arsitektur dan API perpustakaan yang akan kita bicarakan. Jika tidak, lihat dokumentasi
Bereaksi dan
Redux .

Tentang manajemen negara dalam aplikasi JavaScript
Bereaksi menyediakan pengembang dengan dua mekanisme utama untuk mentransfer data ke komponen. Ini adalah properti (properti) dan status. Properti hanya baca dan memungkinkan komponen induk meneruskan atribut ke komponen turunan. Status adalah entitas lokal yang dienkapsulasi dalam komponen yang dapat berubah kapan saja dalam siklus hidup komponen.
Karena keadaan adalah mekanisme yang sangat berguna yang digunakan untuk membuat aplikasi Bereaksi dinamis yang kuat, maka perlu untuk mengelolanya dengan baik. Saat ini ada beberapa perpustakaan yang menyediakan arsitektur yang terstruktur dengan baik untuk mengelola kesehatan aplikasi. Diantaranya adalah
Flux ,
Redux ,
MobX .
Redux adalah perpustakaan yang dirancang untuk membuat wadah yang digunakan untuk menyimpan status aplikasi. Ini menawarkan alat manajemen negara dimengerti pengembang yang berperilaku diprediksi. Perpustakaan ini cocok untuk aplikasi yang ditulis dalam JavaScript murni, serta untuk proyek dalam pengembangan yang beberapa kerangka kerja digunakan. Redux berukuran kecil, tetapi memungkinkan Anda untuk menulis aplikasi yang andal yang bekerja di lingkungan yang berbeda.
Inilah cara membuat repositori Redux:
import { createStore } from 'redux'; const initialState = { auth: { loggedIn: false } } const store = createStore((state = initialState, action) => { switch (action.type) { case "LOG_IN": return { ...state, auth: { loggedIn: true } }; break; case "LOG_OUT": return { ...state, auth: { loggedIn: false } }; break; default: return state; break; } })
Paket react-redux
Paket react-redux menyediakan binding Bereaksi untuk wadah negara Redux, membuatnya sangat mudah untuk menghubungkan aplikasi Bereaksi ke repositori Redux. Ini memungkinkan Anda untuk memisahkan komponen aplikasi Bereaksi berdasarkan hubungannya dengan repositori. Yaitu, kita berbicara tentang jenis komponen berikut:
- Komponen presentasi. Mereka hanya bertanggung jawab atas penampilan aplikasi dan tidak mengetahui keadaan Redux. Mereka menerima data melalui properti dan dapat memanggil panggilan balik, yang juga diteruskan kepada mereka melalui properti.
- Komponen Kontainer. Mereka bertanggung jawab atas pengoperasian mekanisme internal aplikasi dan berinteraksi dengan keadaan Redux. Mereka sering dibuat menggunakan react-redux, mereka dapat mengirim tindakan Redux. Selain itu, mereka berlangganan perubahan negara.
Rincian tentang pendekatan ini dengan pembagian tanggung jawab komponen dapat ditemukan di
sini . Pada artikel ini, kita terutama akan berbicara tentang komponen kontainer yang terhubung ke kondisi Redux menggunakan react-redux.
Paket react-redux memiliki antarmuka yang sangat sederhana. Secara khusus, hal yang paling menarik tentang antarmuka ini adalah sebagai berikut:
<Provider store>
- memungkinkan Anda membuat pembungkus untuk aplikasi Bereaksi dan membuat status Redux tersedia untuk semua komponen kontainer dalam hierarki.connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
- memungkinkan Anda membuat komponen tingkat tinggi. Ini diperlukan untuk membuat komponen kontainer berdasarkan komponen Bereaksi dasar.
Instal react-redux untuk menggunakan paket ini dalam proyek sebagai berikut:
npm install react-redux
Berdasarkan asumsi bahwa Anda telah mengkonfigurasi repositori Redux untuk aplikasi React Anda, berikut adalah contoh menghubungkan aplikasi ke repositori Redux:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import createStore from './createReduxStore'; const store = createStore(); const rootElement = document.getElementById('root'); ReactDOM.render(( <Provider store={store}> <AppRootComponent /> </Provider> ), rootElement);
Sekarang Anda dapat membuat komponen kontainer yang terhubung ke repositori Redux. Ini dilakukan dalam hierarki
AppRootComponent
menggunakan API
connect()
.
Kapan menggunakan connect ()?
▍Membuat komponen kontainer
Seperti yang telah disebutkan, API reaksi-redux
connect()
digunakan untuk membuat komponen kontainer yang terhubung ke repositori Redux. Penyimpanan yang Anda sambungkan diperoleh dari leluhur komponen paling atas menggunakan mekanisme konteks Bereaksi. Fungsi
connect()
tidak diperlukan jika Anda hanya membuat komponen presentasi.
Jika Anda, dalam komponen Bereaksi, perlu menerima data dari penyimpanan, atau Anda perlu mengirim tindakan, atau Anda perlu melakukan keduanya, Anda dapat mengubah komponen biasa menjadi komponen wadah dengan membungkusnya dalam komponen urutan tinggi yang dikembalikan dengan
connect()
dari reaksi-redux. Begini tampilannya:
import React from 'react'; import { connect } from 'react-redux'; import Profile from './components/Profile'; function ProfileContainer(props) { return ( props.loggedIn ? <Profile profile={props.profile} /> : <div>Please login to view profile.</div> ) } const mapStateToProps = function(state) { return { profile: state.user.profile, loggedIn: state.auth.loggedIn } } export default connect(mapStateToProps)(ProfileContainer);
▍ Menghilangkan kebutuhan untuk berlangganan penyimpanan Redux secara manual
Anda dapat membuat komponen kontainer sendiri dan secara manual menandatangani komponen pada repositori Redux menggunakan perintah
store.subscribe()
. Namun, menggunakan fungsi
connect()
berarti menerapkan beberapa peningkatan kinerja dan optimisasi yang mungkin tidak dapat Anda gunakan saat menggunakan mekanisme lain.
Dalam contoh berikut, kami mencoba membuat komponen kontainer secara manual dan menghubungkannya ke repositori Redux dengan berlangganan. Di sini kami berusaha menerapkan fungsi yang sama seperti yang ditunjukkan pada contoh sebelumnya.
import React, { Component } from 'react'; import store from './reduxStore'; import Profile from './components/Profile'; class ProfileContainer extends Component { state = this.getCurrentStateFromStore() getCurrentStateFromStore() { return { profile: store.getState().user.profile, loggedIn: store.getState().auth.loggedIn } } updateStateFromStore = () => { const currentState = this.getCurrentStateFromStore(); if (this.state !== currentState) { this.setState(currentState); } } componentDidMount() { this.unsubscribeStore = store.subscribe(this.updateStateFromStore); } componentWillUnmount() { this.unsubscribeStore(); } render() { const { loggedIn, profile } = this.state; return ( loggedIn ? <Profile profile={profile} /> : <div>Please login to view profile.</div> ) } } export default ProfileContainer;
Selain itu, fungsi
connect()
memberikan fleksibilitas tambahan kepada pengembang, memungkinkan Anda mengonfigurasi komponen kontainer untuk menerima properti dinamis berdasarkan pada properti yang semula diberikan kepada mereka. Ini ternyata sangat berguna untuk mendapatkan seleksi dari keadaan berdasarkan properti, atau untuk menghubungkan generator tindakan ke variabel tertentu dari properti.
Jika aplikasi Bereaksi Anda menggunakan beberapa repositori Redux, kemudian
connect()
membuatnya mudah untuk menentukan repositori spesifik tempat komponen kontainer harus dihubungkan.
Anatomi terhubung ()
Fungsi
connect()
disediakan oleh paket react-redux dapat memakan waktu hingga empat argumen, yang masing-masing opsional. Setelah memanggil fungsi
connect()
, komponen tingkat tinggi dikembalikan yang dapat digunakan untuk membungkus komponen Bereaksi.
Karena fungsi mengembalikan komponen tingkat tinggi, ia perlu dipanggil lagi, melewati komponen Bereaksi dasar untuk mengubahnya menjadi komponen wadah:
const ContainerComponent = connect()(BaseComponent)
Berikut adalah tanda tangan dari fungsi
connect()
:
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
▍ Argumen mapStateToProps
Argumen
mapStateToProps
adalah fungsi yang mengembalikan objek biasa atau fungsi lainnya. Melewati argumen
connect()
berlangganan komponen container ke pembaruan repositori Redux. Ini berarti bahwa fungsi
mapStateToProps
akan dipanggil setiap kali status repositori berubah. Jika Anda tidak tertarik untuk memantau pembaruan status, berikan
connect()
sebagai nilai argumen ini ke
undefined
atau
null
.
Fungsi
mapStateToProps
dideklarasikan dengan dua parameter, yang kedua adalah opsional. Parameter pertama adalah keadaan repositori Redux saat ini. Parameter kedua, jika dilewatkan, adalah objek dari properti yang diteruskan ke komponen:
const mapStateToProps = function(state) { return { profile: state.user.profile, loggedIn: state.auth.loggedIn } } export default connect(mapStateToProps)(ProfileComponent);
Jika objek biasa dikembalikan dari
mapStateToProps
, maka objek
stateProps
dikembalikan dikombinasikan dengan properti komponen. Anda dapat mengakses properti ini di komponen sebagai berikut:
function ProfileComponent(props) { return ( props.loggedIn ? <Profile profile={props.profile} /> : <div>Please login to view profile.</div> ) }
Jika
mapStateToProps
mengembalikan fungsi, maka fungsi ini digunakan sebagai
mapStateToProps
untuk setiap instance komponen. Ini bisa berguna untuk meningkatkan kinerja rendering dan untuk memoizing.
▍ argumen mapDispatchToProps
Argumen
mapDispatchToProps
bisa berupa objek atau fungsi yang mengembalikan objek biasa atau fungsi lainnya. Untuk menggambarkan
mapDispatchToProps
dengan lebih baik, kita membutuhkan generator tindakan. Misalkan kita memiliki generator berikut:
export const writeComment = (comment) => ({ comment, type: 'WRITE_COMMENT' }); export const updateComment = (id, comment) => ({ id, comment, type: 'UPDATE_COMMENT' }); export const deleteComment = (id) => ({ id, type: 'DELETE_COMMENT' });
Sekarang pertimbangkan berbagai kegunaan
mapDispatchToProps
.
Implementasi standar bawaan
Jika Anda tidak menggunakan implementasi
mapDispatchToProps
Anda sendiri, yang diwakili oleh objek atau fungsi, implementasi standar akan digunakan, yang akan mengimplementasikan metode repositori
dispatch()
sebagai properti untuk komponen. Anda dapat menggunakan properti ini dalam komponen seperti ini:
import React from 'react'; import { connect } from 'react-redux'; import { updateComment, deleteComment } from './actions'; function Comment(props) { const { id, content } = props.comment; // props.dispatch() const editComment = () => props.dispatch(updateComment(id, content)); const removeComment = () => props.dispatch(deleteComment(id)); return ( <div> <p>{ content }</p> <button type="button" onClick={editComment}>Edit Comment</button> <button type="button" onClick={removeComment}>Remove Comment</button> </div> ) } export default connect()(Comment);
Transfer objek
Jika suatu objek digunakan sebagai argumen untuk
mapDispatchToProps
, maka setiap fungsi dalam objek akan ditafsirkan sebagai generator tindakan Redux dan dibungkus dengan panggilan ke metode repositori
dispatch()
, yang akan memungkinkannya untuk dipanggil secara langsung. Objek yang dihasilkan dengan action generator,
dispatchProps
, akan dikombinasikan dengan sifat-sifat komponen.
Contoh berikut menunjukkan contoh membangun argumen
mapDispatchToProps
, yang merupakan objek dengan generator tindakan, serta bagaimana generator dapat digunakan sebagai properti komponen Bereaksi:
import React from 'react'; import { connect } from 'react-redux'; import { updateComment, deleteComment } from './actions'; function Comment(props) { const { id, content } = props.comment; // , , const editComment = () => props.updatePostComment(id, content); const removeComment = () => props.deletePostComment(id); return ( <div> <p>{ content }</p> <button type="button" onClick={editComment}>Edit Comment</button> <button type="button" onClick={removeComment}>Remove Comment</button> </div> ) } // const mapDispatchToProps = { updatePostComment: updateComment, deletePostComment: deleteComment } export default connect(null, mapDispatchToProps)(Comment);
Transfer fungsi
Saat menggunakan fungsi
mapDispatchToProps
sebagai argumen
mapDispatchToProps
programmer harus berhati-hati mengembalikan objek
dispatchProps
, yang mengimplementasikan pengikatan generator tindakan menggunakan metode penyimpanan
dispatch()
. Fungsi ini menerima, sebagai parameter pertama, metode
dispatch()
repositori. Seperti halnya
mapStateToProps
, fungsi ini juga dapat menerima parameter opsional
ownProps
kedua, yang menjelaskan pemetaan dengan properti asli yang diteruskan ke komponen.
Jika fungsi ini mengembalikan fungsi lain, maka fungsi yang dikembalikan digunakan sebagai
mapDispatchToProps
, yang dapat berguna untuk meningkatkan kinerja rendering dan memoisasi.
Fungsi pembantu
bindActionCreators()
dari Redux dapat digunakan di dalam fungsi ini untuk mengikat generator tindakan ke metode repositori
dispatch()
.
Contoh berikut menunjukkan penggunaan, dalam peran
mapDispatchToProps
, dari suatu fungsi. Ini juga menunjukkan pekerjaan dengan fungsi bantu
bindActionCreators()
, yang digunakan untuk mengikat generator tindakan untuk bekerja dengan komentar pada
props.actions
dari komponen React:
import React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import * as commentActions from './actions'; function Comment(props) { const { id, content } = props.comment; const { updateComment, deleteComment } = props.actions; // props.actions const editComment = () => updateComment(id, content); const removeComment = () => deleteComment(id); return ( <div> <p>{ content }</p> <button type="button" onClick={editComment}>Edit Comment</button> <button type="button" onClick={removeComment}>Remove Comment</button> </div> ) } const mapDispatchToProps = (dispatch) => { return { actions: bindActionCreators(commentActions, dispatch) } } export default connect(null, mapDispatchToProps)(Comment);
▍Artumen mergeProps
Jika argumen
mergeProps
dilewatkan untuk
connect()
, maka itu adalah fungsi yang mengambil tiga parameter berikut:
stateProps
adalah objek properti yang dikembalikan dari panggilan mapStateToProps()
.dispatchProps
- objek properti dengan generator tindakan dari mapDispatchToProps()
.ownProps
- Properti asli yang diperoleh komponen.
Fungsi ini mengembalikan objek sederhana dengan properti yang akan diteruskan ke komponen yang dibungkus. Ini berguna untuk memetakan bagian kondisi repositori Redux atau generator aksi berbasis properti secara kondisional.
Jika
connect()
tidak melewati fungsi ini, maka implementasi standarnya digunakan:
const mergeProps = (stateProps, dispatchProps, ownProps) => { return Object.assign({}, ownProps, stateProps, dispatchProps) }
▍Argenda yang merepresentasikan objek dengan parameter
Objek opsional, diteruskan ke fungsi
connect()
sebagai argumen keempat, berisi parameter yang dirancang untuk mengubah perilaku fungsi ini. Jadi,
connect()
adalah implementasi khusus dari fungsi
connectAdvanced()
, ia menerima sebagian besar parameter yang tersedia untuk
connectAdvanced()
, serta beberapa parameter tambahan.
Berikut adalah halaman dokumentasi, setelah membaca yang mana Anda dapat mengetahui parameter apa yang dapat digunakan dengan
connect()
, dan bagaimana mereka memodifikasi perilaku fungsi ini.
Menggunakan Fungsi connect ()
▍Buat penyimpanan
Sebelum mengubah komponen Bereaksi menjadi komponen kontainer menggunakan
connect()
, Anda perlu membuat repositori Redux yang mana komponen ini akan terhubung.
Misalkan kita memiliki komponen wadah
NewComment
, yang digunakan untuk menambahkan komentar baru ke publikasi, dan, di samping itu, menampilkan tombol untuk mengirim komentar. Kode yang menggambarkan komponen ini mungkin terlihat seperti ini:
import React from 'react'; import { connect } from 'react-redux'; class NewComment extends React.Component { input = null writeComment = evt => { evt.preventDefault(); const comment = this.input.value; comment && this.props.dispatch({ type: 'WRITE_COMMENT', comment }); } render() { const { id, content } = this.props.comment; return ( <div> <input type="text" ref={e => this.input = e} placeholder="Write a comment" /> <button type="button" onClick={this.writeComment}>Submit Comment</button> </div> ) } } export default connect()(NewComment);
Agar komponen ini dapat digunakan dalam aplikasi, perlu untuk menggambarkan repositori Redux yang komponen ini harus terhubung. Kalau tidak, kesalahan akan terjadi. Ini dapat dilakukan dengan dua cara, yang sekarang akan kita pertimbangkan.
Mengatur properti toko dalam komponen wadah
Cara pertama untuk melengkapi komponen dengan repositori Redux adalah dengan memberikan tautan ke repositori tersebut sebagai nilai properti
store
komponen:
import React from 'react'; import store from './reduxStore'; import NewComment from './components/NewComment'; function CommentsApp(props) { return <NewComment store={store} /> }
Mengatur properti toko di komponen <Provider>
Jika Anda ingin mengatur repositori Redux untuk aplikasi hanya sekali, maka Anda akan tertarik pada metode yang sekarang akan kita pertimbangkan. Biasanya cocok untuk aplikasi yang hanya menggunakan satu repositori Redux.
Paket react-redux memberi pengembang komponen
<Provider>
, yang dapat digunakan untuk membungkus komponen root aplikasi. Ia menerima properti
store
. Diasumsikan bahwa itu adalah tautan ke repositori Redux yang rencananya akan digunakan dalam aplikasi. Properti
store
diteruskan, sesuai dengan hierarki aplikasi, ke komponen kontainer, menggunakan mekanisme konteks Bereaksi:
import React from 'react'; import ReactDOM from 'react-dom'; import store from './reduxStore'; import { Provider } from 'react-redux'; import NewComment from './components/NewComment'; function CommentsApp(props) { return <NewComment /> } ReactDOM.render(( <Provider store={store}> <CommentsApp /> </Provider> ), document.getElementById('root'))
▍OpenProps Access Organization
Seperti yang telah disebutkan, fungsi
mapStateToProps
dan
mapDispatchToProps
mapStateToProps
untuk
connect()
dapat dideklarasikan dengan parameter kedua
ownProps
, yang merupakan properti komponen.
Namun, ada satu masalah. Jika jumlah parameter yang diperlukan dari fungsi yang dideklarasikan kurang dari 2, maka
ownProps
tidak akan dikirimkan. Tetapi jika suatu fungsi dideklarasikan tanpa parameter yang diperlukan atau dengan setidaknya 2 parameter,
ownProps
akan diteruskan.
Pertimbangkan beberapa opsi untuk bekerja dengan
ownProps
.
Deklarasi fungsi tanpa parameter
const mapStateToProps = function() { console.log(arguments[0]);
Dalam situasi ini,
ownProps
dilewatkan, karena fungsi tersebut dinyatakan tanpa parameter yang diperlukan. Akibatnya, kode berikut yang ditulis menggunakan sintaks baru untuk parameter ES6 yang tersisa akan berfungsi:
const mapStateToProps = function(...args) { console.log(args[0]);
Deklarasi fungsi dengan satu parameter
Perhatikan contoh berikut:
const mapStateToProps = function(state) { console.log(state);
Hanya ada satu parameter,
state
. Akibatnya,
arguments[1]
mengambil nilai yang
undefined
karena fakta bahwa
ownProps
tidak ditransmisikan.
Deklarasi fungsi dengan parameter default
const mapStateToProps = function(state, ownProps = {}) { console.log(state);
Hanya ada satu parameter yang diperlukan,
state
, karena parameter kedua,
ownProps
, adalah opsional karena memiliki nilai default. Akibatnya, karena hanya ada satu parameter yang diperlukan,
ownProps
tidak lulus, dan pemetaan dilakukan dengan nilai default yang ditetapkan untuknya, yaitu, dengan objek kosong.
Mendeklarasikan fungsi dengan dua parameter
const mapStateToProps = function(state, ownProps) { console.log(state);
Semuanya diatur dengan sangat sederhana. Yaitu, dalam situasi seperti itu, transfer
ownProps
karena fakta bahwa fungsi tersebut dideklarasikan dengan dua parameter yang diperlukan.
Ringkasan
Setelah menguasai materi ini, Anda belajar tentang kapan dan bagaimana menggunakan API
connect()
disediakan oleh paket react-redux dan dirancang untuk membuat komponen kontainer yang terhubung ke status Redux. Di sini kami berbicara dalam beberapa detail tentang struktur fungsi
connect()
dan cara bekerja dengannya, namun, jika Anda ingin mempelajari lebih lanjut tentang mekanisme ini, khususnya, membiasakan diri dengan kasus penggunaannya, lihatlah bagian
ini pada dokumentasi reux-redux.
Pembaca yang budiman! Apakah Anda menggunakan react-redux dalam proyek Anda?
