Dialog tentang Janji

Apa itu kotak dialog?

Wikipedia mengatakan sebagai berikut:
Kotak dialog (kotak dialog bahasa Inggris) dalam antarmuka pengguna grafis adalah elemen antarmuka khusus, jendela yang dirancang untuk menampilkan informasi dan (atau) menerima respons dari pengguna. Itu mendapat namanya karena melakukan interaksi komputer-pengguna dua arah ("dialog"): mengatakan sesuatu kepada pengguna dan menunggu jawaban darinya.

Kami tertarik
menunggu jawaban darinya
Dengan kata lain, kami membuka jendela modal untuk mendapatkan umpan balik dan melakukan sesuatu setelah itu. Tidak menyerupai apa pun? Dan saya pikir begitu.

Bayangkan sebuah situasi, kami memiliki aplikasi untuk manajemen pengguna.
Skenarionya adalah sebagai berikut.

Di halaman utama, pengguna dapat membuka jendela modal untuk daftar pengguna lain.
Dari daftar Anda dapat membuka jendela modal dengan informasi tentang pengguna, juga di jendela ini ada formulir untuk mengirim surat.

Saat mengirim surat, pengguna membuka jendela modal tentang pengiriman yang berhasil.
Ketika pengguna menutup jendela modal, ia kembali ke jendela modal dari daftar pengguna, tetapi ada tombol untuk menulis surat lain, ketika diklik, pengguna masuk ke halaman pengguna.

Untuk membacanya agak sulit membayangkan tugas ini dalam bentuk diagram urutan.

gambar

Sekarang semuanya jauh lebih sederhana.

Dari sudut pandang kode, membuka jendela modal adalah tindakan sinkron, kita dapat membukanya, di dalamnya dapat ditutup, tetapi bagaimana jika mengubah data di jendela modal, saat menutupnya, Anda perlu mendapatkan data dari sana?

Contoh sederhana, dari jendela modal pengguna, kami mengubah data, kembali ke jendela modal daftar, Anda perlu memperbarui informasi tentang pengguna ini.

Itu berbau asinkronisme ...

Ketika kita membuka modul, kita harus menunggu untuk menutup dan mendapatkan data yang dimasukkan pengguna. Tindakan asinkron dilaksanakan dengan sangat baik dengan janji-janji.

Bahkan, janji sudah diletakkan di diagram kita, kita hanya menandainya sebagai tindakan. Anda dapat mengulanginya sedikit.

gambar

Sekarang semuanya menjadi sederhana ketika pengguna membuka jendela modal, kita menunggu sampai dia menyelesaikan pekerjaannya, setelah itu keputusan dipanggil di promis. Kedengarannya sederhana, mari kita mulai.

Kerangka utama saya adalah reaksi, jadi kami akan segera melakukannya berdasarkan itu. Untuk dapat membuka modal windows dari bagian mana pun dari aplikasi, kami akan menggunakan API Konteks.

Pertama-tama, kita perlu membuat konteks dan tempat penyimpanannya.

// ./Provider.js export const DialogContext = React.createContext(); export const Provider = ({ children, node, Layout, config }) => { const [instances, setInstances] = useState([]); const [events, setEvents] = useState([]); const context = { instances, setInstances, config, events, setEvents }; const Component = instances.map(instance => ( <Layout key={instance.instanceName} component={config[instance.instanceName]} {...instance} /> )); const context = { instances setInstances }; //   state     const child = useMemo(() => React.Children.only(children), [children]); return ( <DialogContext.Provider value={context}> <> {child} {createPortal(Component, node)} </> </DialogContext.Provider> ); }; 

Semuanya sederhana di sini, kami menggunakan useState pertama untuk membuat array jendela modal terbuka. Sesuatu seperti tumpukan.

Yang kedua, useState, diperlukan untuk menambahkan referensi untuk menyelesaikan dan menolak janji. Ini akan kita lihat di bawah.

Kami mengarahkan render melalui portal sehingga kami tidak perlu bertarung jika terjadi sesuatu dengan indeks-z.

Layout adalah komponen yang akan menjadi komponen dasar untuk semua modal windows.

Parameter config hanyalah objek, di mana kuncinya adalah pengidentifikasi jendela modal, dan nilainya adalah komponen dari jendela modal.

 //  config.js export const exampleInstanceName = 'modal/example'; export default { [exampleInstanceName]: React.lazy(() => import('./Example')), }; 

Sekarang kita menulis implementasi metode yang akan membuka modal windows.

Ini akan menjadi pengait:

 export const useDialog = () => { const { setEvents, setInstances, config } = useContext(DialogContext); const open = instance => new Promise((resolve, reject) => { if (instance.instanceName in config) { setInstances(prevInstances => [...prevInstances, instance]); setEvents(prevEvents => [...prevEvents, { resolve, reject }]); } else { throw new Error(`${instance['instanceName']} don't exist in modal config`); } }); return { open }; }; 

Hook mengembalikan fungsi terbuka yang bisa kita gunakan untuk memanggil jendela modal.

 import { exampleInstanceName } from './config'; import { useDialog } from './useDialog'; const FillFormButton = () => { const { open } = useDialog(); const fillForm = () => open(exampleInstanceName) return <button onClick={fillForm}>fill form from modal</button> } 

Dalam opsi ini, kita tidak akan pernah menunggu jendela modal ditutup, kita perlu menambahkan metode untuk menyelesaikan janji:

 // ./Provider.js export const DialogContext = React.createContext(); export const Provider = ({ children, node, Layout, config }) => { const [instances, setInstances] = useState([]); const [events, setEvents] = useState([]); const close = useCallback(() => { const { resolve } = events[events.length - 1]; const resolveParams = { action: actions.close }; setInstances(prevInstances => prevInstances.filter((_, index) => index !== prevInstances.length - 1)); setEvents(prevEvents => prevEvents.filter((_, index) => index !== prevEvents.length - 1)); resolve(resolveParams); }, [events]); const cancel = useCallback((values): void => { const { resolve } = events[events.length - 1]; const resolveParams = { action: actions.cancel, values }; setInstances(prevInstances => prevInstances.filter((_el, index) => index !== prevInstances.length - 1)); setEvents(prevEvents => prevEvents.filter((_el, index) => index !== prevEvents.length - 1)); resolve(resolveParams); }, [events]); const success = useCallback((values) => { const { resolve } = events[events.length - 1]; const resolveParams = { action: actions.success, values }; setInstances(prevInstances => prevInstances.filter((_el, index) => index !== prevInstances.length - 1)); setEvents(prevEvents => prevEvents.filter((_el, index) => index !== prevEvents.length - 1)); resolve(resolveParams); }, [events]); const context = { instances, setInstances, config, events, setEvents }; const Component = instances.map(instance => ( <Layout key={instance.instanceName} component={config[instance.instanceName]} cancel={cancel} success={success} close={close} {...instance} /> )); const context = { instances setInstances }; //   state     const child = useMemo(() => React.Children.only(children), [children]); return ( <DialogContext.Provider value={context}> <> {child} {createPortal(Component, node)} </> </DialogContext.Provider> ); }; 

Sekarang, ketika dalam komponen Layout atau jika ia melewati metode ini ke komponen modal window, metode sukses, batal atau tutup akan dipanggil, kita akan memiliki tekad pada janji yang diperlukan. Di sini konsep seperti tindakan ditambahkan, ini adalah garis yang menjawab dalam status apa dialog diselesaikan. Ini mungkin berguna ketika kita melakukan beberapa tindakan setelah jendela modal dijalankan:

 const { useState } from 'rect'; import { exampleInstanceName } from './config'; import { useDialog } from './useDialog'; const FillFormButton = () => { const [disabled, setDisabled] = useState(false); const { open } = useDialog(); const fillForm = () => open(exampleInstanceName) .then(({ action }) => { if (action === 'success') setDisabled(true); }); return <button onClick={fillForm} disabled={disabled}>fill form from modal</button> } 

Itu saja. Tetap menambahkan transfer parameter dari jendela modal ke jendela modal dari fungsi terbuka. Yah, saya pikir Anda dapat menangani ini sendiri, tetapi jika Anda terlalu malas, maka ada paket siap pakai yang dapat Anda gunakan dalam proyek Anda.

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


All Articles