Redux: Bagaimana cara memanggil tindakan tanpa menggunakan @connect?

Dibuat pada 30 Jul 2015  ·  32Komentar  ·  Sumber: reduxjs/redux

Saya memiliki wadah header yang mengirimkan data gambar (url, ukuran) ke komponen header menggunakan

@connect(state => ({
  header: state.header
}))
export default class HeaderContainer extends Component {
 /// pass props.header data to child Header which renders image.
}

Lalu saya memiliki komponen lain yang perlu memanggil tindakan header untuk memperbarui status header. Itu tidak menggunakan negara, itu hanya menembakkan tindakan. Afaik saya perlu melakukan sesuatu seperti ini:

const { dispatch } = this.props
const actions = bindActionCreators(headerActions, dispatch)

Masalahnya adalah, this.props.dispatch sepertinya hanya tersedia jika Anda menggunakan dekorator @connect . Komponen kedua sama sekali tidak tertarik dengan status header. Apakah saya benar-benar perlu menggunakan koneksi di sini atau dapatkah itu mengikat tindakan dengan cara yang berbeda? Rasanya salah menggunakan @connect jika saya tidak menggunakan datanya.

question

Komentar yang paling membantu

Anda dapat mengirimkan dispatch ke komponen itu secara manual sebagai prop.

Semua 32 komentar

Saya tidak yakin apakah ini cara yang "benar" atau tidak, tetapi Anda dapat mengakses toko melalui konteksnya. Lihat komponen Connector sebagai contoh:
https://github.com/gaearon/react-redux/blob/master/src/components/createConnector.js

Saya tidak mengikuti Anda. Saya baik-baik saja mengakses toko dengan menggunakan @connect. Saya mencari cara untuk mengikat / memanggil tindakan dalam sebuah komponen tanpa menggunakan @connect.

Fungsi dispatch adalah metode penyimpanan. Jika Anda membutuhkannya di komponen Anda tetapi tidak ingin menggunakan @connect , maka Anda dapat mengakses penyimpanan melalui konteks dan menggunakan metode pengirimannya:

class MyComponent extends Compoenent {
    static contextTypes = {
        store: React.PropTypes.object.isRequired,
    }

    render() {
         const { dispatch } = this.context.store
         const actions = bindActionCreators(headerActions, dispatch)
    }
}

Anda harus meneruskan pengiriman dari komponen induk, atau tindakan yang sudah terikat ke pengiriman. Itulah cara yang saya yakini, konteks juga berfungsi, meskipun itu solusinya

Terima kasih telah menjelaskan ini! Aku mengerti sekarang.

Anda dapat mengirimkan dispatch ke komponen itu secara manual sebagai prop.

Saya juga agak bingung dengan masalah ini.

Jika saya memahaminya dengan benar, kita perlu memiliki dispatch tersedia melalui props komponen (agar dapat mengirimkan tindakan dari komponen itu) atau memberikan pembuat tindakan yang sudah terikat ke dispatch , dari a komponen induk. Namun kedua solusi tersebut harus memiliki komponen induk yaitu connect ed sehingga pengiriman dapat dilakukan melalui propsnya.

Jadi pada akhirnya kami hanya mentransfer ketergantungan kami dari dispatch ke komponen induk. Dan bagaimana Anda akan melakukannya jika tidak ada orang tua yang connect ed?

Misalnya, bagaimana jika kita berada dalam hierarki komponen yang dalam:

Provider
  Router
    AppContainer
     ...
       ...
         ...
           TheComponentThatNeedDispatch

dan jika tidak ada orang tua yang perlu terhubung ke status redux?

Memiliki pengiriman yang tersedia untuk komponen sebagai efek samping penggunaan connect tampaknya menempatkan kita dalam situasi di mana itu adalah prasyarat untuk memiliki satu induknya menjadi connect ed untuk menjadi mampu dispatch tindakan. Ini terasa aneh karena seharusnya tidak ada korelasi antara kemampuan komponen dengan dispatch tindakan dan kebutuhan untuk menggunakan connect untuk membaca dari status redux.

Saya tahu bahwa kita masih dapat mengakses dispatch dari konteks komponen (melalui store.dispatch ) tetapi karena itu bukan cara yang disarankan ...

Apa yang Anda pikirkan?

Terima kasih!

Ini terasa aneh karena seharusnya tidak ada korelasi antara kemampuan komponen untuk mengirimkan tindakan dan kebutuhan untuk menggunakan koneksi untuk membaca dari status redux.

Kenapa aneh? Pikirkan connect sebagai "sambungkan ke Redux" dan bukan hanya "sambungkan ke bagian dari status Redux". Maka masuk akal: untuk dapat dispatch baik komponen itu sendiri, atau beberapa induknya, harus connect() ed ke Redux.

Dengan React Redux API saat ini, tidak nyaman untuk terhubung ke Redux tanpa juga memilih status. Anda harus menulis sesuatu seperti connect(state => ({}))(MyComponent) (mengembalikan objek kosong). Inilah mengapa kami menjelajahi API alternatif untuk itu yang menghasilkan dispatch warga kelas satu dan berencana untuk menambahkan API untuk meraih "hanya dispatch ".

Apakah ini masuk akal?

Pikirkan koneksi sebagai "terhubung ke Redux" dan bukan hanya "terhubung ke bagian dari status Redux".

Benar-benar masuk akal sekarang :).

Tidak sabar untuk menggunakan API baru .

Terima kasih banyak, menggunakan Redux sangat menyenangkan!

Ini terlihat bagus!

@gaearon hey Dan bisakah Anda memberi saya tip tentang cara menggunakan bindActionCreators dengan komponen bersarang:

"AddProduct" - terhubung ke redux (lihat di bawah)
__ "Daftar Produk"
____ "Tampilan Produk".

Saya ingin ProductView dapat dikirim, tetapi hanya master "Tambahkan Produk" yang memiliki:

function appState(state) {
    return {...};
}

export default connect(appState)(AddProduct)

Anda juga dapat connect() komponen bersarang, atau Anda dapat mengirimkan dispatch sebagai properti.

terima kasih Dan, sangat menghargai bantuan Anda. sangat suka redux juga!

pertanyaan lain jika saya boleh:
dapatkah saya menempatkan permintaan posting API server dari dalam peredam itu sendiri?
ketika saya POST ke database (mongodb), item tersebut mendapat "_id" yang saya ingin miliki dalam status redux saya. haruskah pengiriman tersebut ditempatkan sebagai panggilan balik untuk permintaan POST?

Terima kasih

dapatkah saya menempatkan permintaan posting API server dari dalam peredam itu sendiri?

Jelas tidak, pereduksi harus merupakan fungsi murni yang bebas dari efek samping apa pun.

ketika saya POST ke database (mongodb), item tersebut mendapat "_id" yang saya ingin miliki dalam status redux saya. haruskah pengiriman tersebut ditempatkan sebagai panggilan balik untuk permintaan POST?

Iya.

Silakan lihat panduan ini: http://rackt.github.io/redux/docs/advanced/AsyncActions.html

terima kasih Dan, bekerja dengan baik (y)

jika saya menggunakan rendering server untuk katakanlah meminta pengguna saat ini masuk,
dapatkah saya melewati pengambilan asinkron dari toko, dan melakukannya di server?

Jika saya menggunakan rendering server untuk katakanlah meminta pengguna saat ini masuk, dapatkah saya melewati pengambilan asinkron dari toko, dan melakukannya di server?

Anda dapat membuat penyimpanan di server, menunggu tindakan asinkron selesai, lalu merender.
Lihat juga http://rackt.github.io/redux/docs/recipes/ServerRendering.html

Saya mungkin melewatkan sesuatu yang penting, tetapi mengapa tidak menerapkan pengiriman sebagian ke semua pembuat tindakan selama inisialisasi aplikasi? Kemudian Anda dapat menelepon dari mana saja tanpa khawatir tentang bagaimana mendapatkan referensi untuk pengiriman.

@mpoisot : karena Anda harus mengetahui, mengimpor, mengikat, dan mendistribusikan _every_ pembuat tindakan potensial saat memulai aplikasi. Antara lain, itu tidak membantu dalam situasi seperti pemisahan kode.

@markerikson Saya sudah harus mengetahui semua reduksi di app init sehingga saya dapat menelepon createStore . Saya membayangkan menelepon bindAllActionCreators(store.dispatch) di baris berikutnya.

Benar, Anda mungkin akan menarik lebih banyak kode daripada yang sebenarnya Anda gunakan. Tetapi jika itu menjadi perhatian maka jangan lakukan dengan cara ini. Atau bagi kumpulan peredam Anda (peredam + pembuat tindakan + penyeleksi) menjadi kumpulan yang lebih kecil dan lebih terfokus. Atau hanya mengikat beberapa pembuat aksi.

Apakah ada hukuman kinerja yang buruk karena melakukan ini? Atau entah bagaimana itu mengarah ke jalan yang mengerikan menuju neraka coding?

@ Mpoisot : sebenarnya tidak ada masalah kinerja yang bisa saya pikirkan. Namun, itu membatasi kemampuan untuk diuji dan digunakan kembali.

Penggunaan yang tepat dari connect menghasilkan pendekatan Injeksi Ketergantungan ringan. Komponen "biasa" hanya mengetahui bahwa ia diberi beberapa fungsi sebagai penyangga, dan ia harus memanggil fungsi itu sesuai kebutuhan. Itu sebenarnya tidak peduli apakah itu panggilan balik yang diturunkan langsung oleh beberapa komponen induk, atau pembuat tindakan yang sudah terikat sebelumnya. Artinya, komponen tersebut dapat digunakan kembali dengan cara yang mudah, dan juga membuat pengujian menjadi jauh lebih mudah. Di sisi lain, melakukan sesuatu seperti mengimpor langsung hasil penyimpanan dalam mengikat komponen ke contoh penyimpanan tertentu dan implementasi, itulah mengapa tidak disarankan (sesuai dengan FAQ Redux: http://redux.js.org/docs/faq/ StoreSetup.html # store-setup-multiple-store). Jika saya memahami apa yang Anda tanyakan dengan benar, pada dasarnya situasinya sama dengan mengimpor dan mereferensikan toko secara langsung.

Ah poin yang bagus, yang menerapkan sebagian pengiriman dalam tindakan pembuat akan sama dengan mengimpor toko sebagai tunggal, yang tidak disukai. Saya mencoba mempelajari alasannya, dan saya menemukan beberapa tempat di mana Dan Abramov mengatakan bahwa toko tunggal tidak disukai karena rendering sisi server (yang tidak akan pernah digunakan kebanyakan orang), tetapi aneh dia tidak pernah menyebutkan pengujian (yang harus dilakukan semua orang, atau setidaknya merasa tidak enak karena tidak melakukan).

Yang membuat saya berpikir, pasti Anda dapat membuat objek tunggal toko yang tokonya dapat diperbarui dengan berbagai toko untuk pengujian? Alih-alih langsung mengekspor toko itu sendiri, kembalikan melalui StoreSingleton.getStore() , dan ubah toko saat ini melalui StoreSingleton.setStore() . Jadi dalam hal pengujian, Anda tidak akan terikat pada satu contoh toko. Namun, saya dapat melihat mengapa ini tidak berfungsi di lingkungan server berulir.

@mpoisot Anda baru saja menjelaskan apa yang dilakukan Penyedia / penghubung. ;)

Seringkali saya memiliki komponen "bodoh" yang suatu hari perlu dikirim (atau tindakan yang sudah terikat sebelumnya). Jadi saya membungkusnya dengan koneksi, atau mungkin meneruskan barang-barang dari komponen yang mengandung yang terhubung. Seringkali terasa seperti banyak kabel dan alat peraga yang lewat hanya untuk menghindari pengiriman yang dapat diakses secara global. Untuk mapStateToProps () ada keuntungan kinerja yang luar biasa dengan Provider / connect (). Dan untuk menggunakan kembali komponen bodoh, sangat masuk akal untuk mengekstrak logika pengiriman ke komponen urutan yang lebih tinggi.

Tapi saya sudah cukup sering menghadapi skenario ini untuk bertanya-tanya mengapa. Dan ternyata jawabannya adalah "sehingga Anda dapat melakukan rendering di sisi server suatu hari nanti". (Harap perbaiki saya jika saya salah).

Saat ini, connect() hanya memberi Anda metode dispatch dari penyimpanan Provider , tetapi di masa mendatang, mungkin itu bisa berubah. Kami mungkin menambahkan fungsionalitas tambahan, seperti integrasi dengan alat dev untuk memberi tahu Anda komponen React apa yang menjadi sumber tindakan yang diaktifkan, misalnya. Atau seseorang mungkin membuat komponen yang meningkatkan penyimpanan dengan cara lain dengan mengambil penyimpanan dalam konteks, meningkatkannya entah bagaimana, dan kemudian meneruskan penyimpanan yang ditingkatkan itu ke pohon komponen. Jika Anda telah mengikat pembuat tindakan Anda ke toko tunggal, Anda berpotensi menelepon dispatch .

Ya, beberapa eksperimen "komponen / keadaan terenkapsulasi" yang saya lihat berhasil dengan pendekatan itu. Hal bagus tentang gagasan itu adalah bahwa komponen lain tidak perlu mengetahui apa pun yang diubah, karena komponen pembungkusnya masih hanya mengambil this.context.store dan menggunakan dispatch sesuai kebutuhan.

Saya telah berada di kedua sisi ini -

Dalam aplikasi utama saya, kami memperlakukan toko sebagai tunggal dan menggunakan fungsi getStore() tersedia secara global. Kami tidak menggunakan rendering sisi server. Kami masih menggunakan Provider dan connect untuk mapStateToProps .

Di sisi lain, saya telah membangun aplikasi eksperimental tempat saya membungkus toko (seperti @jimbolla dan @markerikson disebutkan) di berbagai tempat dalam hierarki komponen, dan keduanya dispatch dan getState kaleng berubah di seluruh aplikasi, yang berarti mereka _have_ untuk disambungkan ke seluruh aplikasi (baik melalui context atau props ) dan tidak boleh lajang.

Bergantung pada apa yang ingin Anda capai, saya pikir barang-barang toko tunggal itu layak, tetapi secara pribadi saya perlahan-lahan menjauh darinya.

Ya. Anda tentu _dapat_ memperlakukan toko sebagai satu-satunya yang dapat diakses, tetapi hal itu membatasi Anda, tidak dianggap idiomatis, dan saya tidak melihat keuntungan nyata untuk melakukannya.

Terima kasih, masukan yang bagus. Dapatkah seseorang memposting link yang menunjukkan bungkus toko?

@tokopedia

Berikut adalah salah satu komentar Dan yang menggambarkan bagaimana membungkus dispatch bisa berguna:

https://github.com/reactjs/redux/issues/822#issuecomment -145271384

Anda mungkin harus membaca seluruh utas untuk lebih memahami apa motivasi itu.

Secara khusus, perhatikan bagaimana dispatch dibungkus (saya telah menyorotinya):

wrappeddispatch

Maaf telah membajak posting lama ini karena saya menghadapi kebingungan yang sama, ingin mengirimkan tindakan tanpa terhubung.

export default class App extends Component {
...
  componentDidMount() {
    //registering event listener
    BackgroundGeolocation.on('location', this.onLocation, this.onError);
  }

  onLocation(location) {
   //wishing to dispatch an action to update variable in store
  }

  render() {
    return (
      <Provider store={store}>
        <AlertProvider>
          <MainNavigator screenProps={{ isConnected: this.state.isConnected }} />
        </AlertProvider>
      </Provider>
    );
  }
}

Dari apa yang saya pahami, saya tidak mungkin terhubung ke penyimpanan dalam komponen ini karena kita baru saja mengkonfigurasi dan meneruskan penyimpanan ke Provider . Bagaimana mungkin saya mengirimkan tindakan dalam acara onLocation ?

@isaaclem : baik, dalam kasus khusus itu, Anda _do_ memiliki referensi ke toko, jadi Anda bisa langsung menghubungi store.dispatch(someAction) .

Pilihan lainnya adalah merestrukturisasi struktur komponen Anda sehingga beberapa komponen _inside_ <Provider> melakukan perilaku geolokasi latar belakang, dan juga dapat dihubungkan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat