Redux: Middleware rusak

Dibuat pada 6 Jun 2018  ·  3Komentar  ·  Sumber: reduxjs/redux

Serangga

Pola middleware penting telah rusak. IMO sebagian besar solusi middleware merangkum kekhawatiran mereka sendiri dan tidak tergantung pada keberadaan middleware lainnya. Perubahan dibuat baru-baru ini untuk memecahkan pola yang hanya menyebabkan masalah kecil untuk subset middleware tertentu: pola yang menunjukkan perilaku berbeda saat berinteraksi dengan middleware lain selama jalur inisialisasi applyMiddleware .

Berikut beberapa contohnya:

// Make state aware of browser media queries
const mediaQueries = (mediaQueries = defaultMediaQueries): Middleware => store => {
  if (typeof window !== 'undefined') {
    const reverseMap = createReverseMap(mediaQueries)

    const handleMediaChange = ({media, matches}: MediaChangedActionPayload) =>
      store.dispatch(mediaChanged(reverseMap[media], matches))

    const addMatchListener = (media: string) => {
      const match = window.matchMedia(media)
      match.addListener(handleMediaChange)
      return match.matches
    }

    values(mediaQueries).forEach(media => 
      handleMediaChange({media, matches: addMatchListener(media)}))
  }

  return next => (action: any) => next(action)
}

Contoh lain:

// Make state aware of user adblockers
const adBlockDetection: Middleware = store => {
  if (typeof document !== 'undefined' && !document.getElementById('XMpADSwgbPUC')) {
    store.dispatch({type: AD_BLOCKER_DETECTED, payload: true})
  }
  return next => (action: any) => next(action)
}

Contoh lain:

// Make state aware of socket connectivity and allow synchronisation of actions
const socketMiddleware = ({actionCreator, url, dataSync}) => store => {
  const socket = new WebSocket(url.replace(/(http|https)/, 'ws'))

  socket.addEventListener('message', ({data}) => {
    store.dispatch(JSON.parse(data))
  })

  socket.addEventListener('open', () => {
    socket.send(syncCreator(CONNECT_TO_DOMAIN, store.getState(), null, socket))
    store.dispatch(actionCreator({connected: true}))
  })

  socket.addEventListener('close', reason => {
    store.dispatch(actionCreator({connected: false}))
  })

  return next => action => {
    if (dataSync.hasOwnProperty(action.type)) {
      socket.send(syncCreator(action.type, store.getState(), action.payload, socket))
    }
    return next(action)
  }
}

Apa perilaku saat ini?

Kesalahan berikut terjadi selama applyMiddleware , pada dasarnya merusak aplikasi:

Uncaught Error: Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch

Memfaktorkan ulang middleware di atas untuk ditutup oleh fungsi next => (seperti di bawah) tidak ada bedanya (tetapi jelas juga bukan solusi yang layak).

// Still broken:
const mediaQueries = (mediaQueries = defaultMediaQueries): Middleware => store => next => {
  // ...middlewareCodeGoesHere...
  return (action: any) => next(action)
}

Apa perilaku yang diharapkan?

Jangan merusak aplikasi. Catat peringatan jika Anda mau, jadi saya bisa mengabaikannya, karena dalam 100% kasus penggunaan saya _Saya tidak peduli apakah middleware lain dapat menangani pengiriman itu_. Saya sangat curiga bahwa ada (atau seharusnya) sangat sedikit alasan yang sah mengapa pengiriman apa pun dari dalam konteks middleware harus pernah berinteraksi dengan middleware lain di tumpukan, dan jika ya, saya akan menganggap bahwa kode berbau (itu akan menempatkan dependensi pesanan implisit pada middleware setidaknya).

Versi Redux mana, dan browser serta OS mana yang terpengaruh oleh masalah ini?

Bekerja sampai PR ini .

Komentar yang paling membantu

@markerikson Ya, saya telah melihat masalah itu. Masalah utama yang "dipecahkan" oleh desain baru adalah ini:

Inilah masalahnya: Listener tersebut aktif saat Anda menerapkan middleware, jadi memanggil

Ini adalah IMO, detail implementasi yang harus ditangani oleh pengembang aplikasi, bukan sesuatu yang seharusnya _memecahkan cara kerja sebagian besar middleware_. Dengan peringatan alih-alih membuat kesalahan, pengembang aplikasi dapat mengidentifikasi masalah, dan memfaktorkan ulang middleware mereka sendiri untuk mengatasinya.

Dalam kondisi saat ini, semua middleware yang ada, termasuk middleware pihak ke-3, yang menggunakan pola pengiriman internal ini (pada dasarnya apa pun yang perlu membuat instance pendengar pada apa pun), rusak.

Sayangnya, tetap menggunakan 3.x bukanlah pilihan bagi kami, karena kami menggunakan TypeScript, dan hanya 4.x yang memiliki pengetikan yang benar, dan secara umum, kami lebih suka tidak terjebak dengan versi lama dari bagian inti kami logika aplikasi bahkan jika pengetikan tidak menjadi masalah.

Dan menurut saya, bahkan pesan kesalahan itu sendiri mengisyaratkan betapa tidak pentingnya itu sebenarnya: "masalahnya" adalah Other middleware would not be applied to this dispatch , yang sangat jarang diinginkan, dan sejauh ini, hanya menjadi masalah untuk satu spesifik kasus penggunaan, di mana middleware analitik bergantung pada tindakan yang dikirim dari router.

Penting untuk dicatat, "perbaikan" di redux sekarang juga merusak kode yang dimaksudkan untuk diperbaiki . Ini merusak middleware router. Sekarang pembuat middleware tersebut (dan semua middleware serupa lainnya) perlu merilis versi 4.x yang kompatibel dari lib mereka, yang sekarang perlu mengekspos detail implementasi dari tindakan "store ready" yang dikirim secara manual, yang harus diterapkan oleh konsumen.

Penggunaan perpustakaan middleware telah berubah dari hanya mengimpor paket, dan memasukkan ke dalam array middlewares, sekarang juga mengharuskan pembuat aplikasi untuk menemukan beberapa cara hacky untuk mengirimkan tindakan "siap simpan" yang sewenang-wenang beberapa saat setelah toko selesai dibuat, tetapi sebelum digunakan. Dan sekarang SEMUA middleware mereka diharapkan harus mematuhi jenis tindakan yang sama, jika tidak, pembuat aplikasi perlu mengirimkan beberapa tindakan "siap simpan", dengan berbagai jenis yang cocok dengan API apa pun yang diterapkan oleh pembuat middleware.

Ini adalah kekacauan yang nyata, dan "penyembuhan" jelas jauh lebih buruk daripada "penyakit" dalam kasus ini.

Semua 3 komentar

Proses init middleware secara eksplisit diubah di 4.0 di PR yang Anda tautkan. Ini adalah keputusan desain yang disengaja, dan dimaksudkan untuk menyelesaikan #1240.

Saya tidak yakin saya memiliki saran langsung untuk kasus penggunaan Anda, selain mencoba mengubah logika middleware Anda untuk menunggu beberapa tindakan "toko siap" yang dikirim secara manual. Anda juga dapat mempertimbangkan untuk tetap menggunakan 3.x sebagai gantinya.

@markerikson Ya, saya telah melihat masalah itu. Masalah utama yang "dipecahkan" oleh desain baru adalah ini:

Inilah masalahnya: Listener tersebut aktif saat Anda menerapkan middleware, jadi memanggil

Ini adalah IMO, detail implementasi yang harus ditangani oleh pengembang aplikasi, bukan sesuatu yang seharusnya _memecahkan cara kerja sebagian besar middleware_. Dengan peringatan alih-alih membuat kesalahan, pengembang aplikasi dapat mengidentifikasi masalah, dan memfaktorkan ulang middleware mereka sendiri untuk mengatasinya.

Dalam kondisi saat ini, semua middleware yang ada, termasuk middleware pihak ke-3, yang menggunakan pola pengiriman internal ini (pada dasarnya apa pun yang perlu membuat instance pendengar pada apa pun), rusak.

Sayangnya, tetap menggunakan 3.x bukanlah pilihan bagi kami, karena kami menggunakan TypeScript, dan hanya 4.x yang memiliki pengetikan yang benar, dan secara umum, kami lebih suka tidak terjebak dengan versi lama dari bagian inti kami logika aplikasi bahkan jika pengetikan tidak menjadi masalah.

Dan menurut saya, bahkan pesan kesalahan itu sendiri mengisyaratkan betapa tidak pentingnya itu sebenarnya: "masalahnya" adalah Other middleware would not be applied to this dispatch , yang sangat jarang diinginkan, dan sejauh ini, hanya menjadi masalah untuk satu spesifik kasus penggunaan, di mana middleware analitik bergantung pada tindakan yang dikirim dari router.

Penting untuk dicatat, "perbaikan" di redux sekarang juga merusak kode yang dimaksudkan untuk diperbaiki . Ini merusak middleware router. Sekarang pembuat middleware tersebut (dan semua middleware serupa lainnya) perlu merilis versi 4.x yang kompatibel dari lib mereka, yang sekarang perlu mengekspos detail implementasi dari tindakan "store ready" yang dikirim secara manual, yang harus diterapkan oleh konsumen.

Penggunaan perpustakaan middleware telah berubah dari hanya mengimpor paket, dan memasukkan ke dalam array middlewares, sekarang juga mengharuskan pembuat aplikasi untuk menemukan beberapa cara hacky untuk mengirimkan tindakan "siap simpan" yang sewenang-wenang beberapa saat setelah toko selesai dibuat, tetapi sebelum digunakan. Dan sekarang SEMUA middleware mereka diharapkan harus mematuhi jenis tindakan yang sama, jika tidak, pembuat aplikasi perlu mengirimkan beberapa tindakan "siap simpan", dengan berbagai jenis yang cocok dengan API apa pun yang diterapkan oleh pembuat middleware.

Ini adalah kekacauan yang nyata, dan "penyembuhan" jelas jauh lebih buruk daripada "penyakit" dalam kasus ini.

Masih mungkin untuk membuat setiap contoh Anda berfungsi. Kirimkan saja setelah applyMiddleware. Mungkin dalam semacam fungsi setupMiddleware(store) atau penambah toko.

Kesalahan sengaja diperkenalkan sebagai alternatifnya adalah untuk memungkinkan pengguna mencapai kasus tepi yang memiliki penyebab yang sangat tidak jelas (kecuali jika Anda terbiasa dengan internal applyMiddleware ). Redux mengambil sikap mencegah kesalahan pengguna bila memungkinkan, jadi ini tidak akan hilang.

Salah satu alternatif mungkin semacam panggilan balik yang dapat didaftarkan middleware sebagai semacam acara afterApply . Maka Anda akan dijamin untuk dikirim pada waktu yang tepat, setelah semuanya diterapkan dan teratur. Itu akan menarik untuk dipikirkan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat