Menggunakan fungsi connect () dari react-redux

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 .

gambar

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:

  1. 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.
  2. 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:

  1. <Provider store> - memungkinkan Anda membuat pembungkus untuk aplikasi Bereaksi dan membuat status Redux tersedia untuk semua komponen kontainer dalam hierarki.
  2. 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 --save 

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]); // state console.log(arguments[1]); // ownProps }; 

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]); // state console.log(args[1]); // ownProps }; 

Deklarasi fungsi dengan satu parameter


Perhatikan contoh berikut:

 const mapStateToProps = function(state) { console.log(state); // state console.log(arguments[1]); // undefined }; 

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); // state console.log(ownProps); // {} }; 

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); // state console.log(ownProps); // ownProps }; 

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?

Source: https://habr.com/ru/post/id423157/


All Articles