Creamos varias aplicaciones de interfaz de usuario interna (UI) con React dentro de eBay. Los modales, o ventanas emergentes, se usan ampliamente para crear estas aplicaciones de interfaz de usuario complejas. Abren una ventana separada para proporcionar información adicional para los usuarios y actúan de manera similar a un usuario que abre una nueva ventana del navegador, excepto que, con modales, un usuario no puede salir hasta que se cierre.
El año pasado, desarrollamos un nuevo enfoque para administrar modales en eBay para ayudar a optimizar los flujos de trabajo y respaldar proyectos más amplios. Recientemente lanzamos nuestro nuevo enfoque para administrar modales en código abierto para compartir con nuestra comunidad tecnológica.
Cómo estamos reinventando los modales
En una aplicación de una sola página, generalmente usamos history.push(‘/some-page’) para cambiar de página. Pero para los modales, anteriormente no teníamos una forma conveniente como modal.show/hide para administrar fácilmente los modales. Bajo nuestro proceso heredado, usamos un método declarativo para administrar modales en proyectos.
Digamos que necesitamos crear un modal como el siguiente:
El cuadro de diálogo se utiliza para crear un ticket JIRA. Se puede mostrar desde muchos lugares, desde el encabezado hasta el menú contextual y la página de lista. Tradicionalmente, habíamos declarado componentes modales con una etiqueta JSX. Pero luego la pregunta se convirtió en: “¿Dónde debemos declarar la etiqueta?”
La opción más común era declararlo dondequiera que se usara. Pero el uso de modales de forma declarativa no se trata solo de una etiqueta JSX, sino también de mantener el estado del modal, como la visibilidad, los parámetros en el componente contenedor. Si miramos hacia atrás a la comparación entre las páginas y el patrón de modales citado anteriormente, encontramos que sería útil tener una API similar para modales, como un administrador de enrutador para páginas:
// Router definition for pages
// Modals declaration
Luego, podemos usar un administrador modal bien diseñado para administrar estos modales:
ModalManager.show('/jira/create');
// or with some props passed to the modal component
ModalManager.show('/user/edit', { userId: 666 });
Para ocultar el modal, podríamos usar ModalManager.hide(‘/user/edit’). El administrador modal proporciona un componente de orden superior que puede manejar la transición con elegancia al mostrar/ocultar un modal.
Con base en esta idea, creamos una pequeña utilidad llamada nice-modal-react para ayudar a administrar estos elementos. Después de usarlo internamente durante un año, lo hemos abierto en:github.com/eBay/nice-modal-react.
En general, usamos React Context para persistir el estado de todos los modales globalmente, luego proporcionamos una API amigable para administrar el estado. Para obtener más guías de uso, visite el reademd.md en el repositorio. Proporciona API muy flexibles para abordar varios escenarios.
A continuación, veamos el ejemplo de uso de esta utilidad.
Creando un buen modal
Para crear un modal, puede usar el componente de orden superior. Tomemos el componente modal de Ant.Design por ejemplo:
import { Modal } from 'antd';
import NiceModal, { useModal } from '@ebay/nice-modal-react';const HelloModal = NiceModal.create(({ name }) => {
// Use the hook to manage modal state
const modal = useModal();
return (
title="Hello Antd"
onOk={() => modal.hide()}
onCancel={() => modal.hide()}
afterClose={() => { modal.hideResolve(); modal.remove(); }}
>
Hello ${name}!
);
});
export default HelloModal;
Al utilizar el método de creación para crear un contenedor de componente de orden superior de su componente modal, garantiza que el código del componente no se ejecute antes de que sea visible. Y elimina el nodo DOM después de que el modal sea invisible. Además, se mantiene la transición de mostrar/ocultar un modal.
El enlace useModal devuelve un controlador modal para administrar el estado modal con una API intuitiva. Puede cerrar el modal en el propio componente modal sin necesidad de mantener el estado de visibilidad fuera del componente.
Usando un buen modal
Después de crear el modal, puede usarlo con la API de NiceModal. Primero, envuelva su aplicación con NiceModal.Provider:
import NiceModal from '@ebay/nice-modal-react';
ReactDOM.render(
,
document.getElementById('root'),
);
Entonces puedes usarlo con un gancho:
import NiceModal, { useModal } from '@ebay/nice-modal-react';
import HelloModal from './HelloModal';
// ...
const modal = useModal(HelloModal);
// Show the modal and pass arguments as props
modal.show({ name: 'Nate' });
// ...
Además del uso básico, existen API muy flexibles para usar el modal. A continuación se muestran solo ejemplos:
// Use modal component with the global method
NiceModal.show(UserInfoModal, { userId: 666 });
// Or using React hook
const modal = NiceModal.useModal(UserEditModal);
// You can also use it by id
const modal = NiceModal.useModal('/user/info/edit')
// Show the modal
modal.show({ userId: 666 });
// After use info updated, refresh the user list
modal.show({ userId: 666 }).then(refreshUserList);
// Wait for the hide transition
await modal.hide();NOTE: if you use the modal by id, then you need to declare it somewhere or register it:
// Declare the modal directly
// or by register api
NiceModal.register('/user/info/edit', UserInfoModal)
// or by ModalDef
Ventajas
Con base en este enfoque, se podrían resolver muchos aspectos de la dificultad de usar modales en React:
- Fácil de aislar modales como componentes separados.
- Sin control. Puede cerrar modal en el componente modal.
- desacoplado. No es necesario importar un componente modal para usarlo. Los modales se pueden administrar por id. Esto es como administrar páginas por URL con React Router.
- El código de su componente modal no se ejecuta cuando es invisible.
- No rompe las transiciones de mostrar/ocultar un modal.
- Basado en promesas. Además de usar accesorios para interactuar con el modal del componente principal, puede hacerlo más fácilmente si lo promete.
- Es independiente, por lo que es fácil de integrar con cualquier biblioteca de interfaz de usuario.
Resumen
En este artículo, presentamos un nuevo enfoque para administrar cuadros de diálogo, ventanas emergentes y cajones basado en lo esencial del patrón de interfaz de usuario modal. La solución ya está abierta en: github.com/eBay/nice-modal-react. Para ver demostraciones en vivo, también puede consultar: ebay.github.io/nice-modal-react/.