Saltar al contenido principal

State Management

Abrir en ChatGPT

Crear experiencias de usuario dinámicas y fluidas a menudo requiere que el estado de tu aplicación web se refleje en la URL y se mantenga a través de eventos de navegación en el navegador. Puedes lograr esto sin recargar la página aprovechando las actualizaciones de parámetros de URL y la gestión del estado del historial del navegador. Esto garantiza que los usuarios puedan compartir, marcar o regresar a vistas específicas con la aplicación completamente consciente de sus interacciones previas.

Actualización de la URL

Cuando el estado de una página web cambia, como al filtrar una lista de productos o navegar a través de diferentes vistas, a menudo necesitas que la URL refleje esos cambios. Puedes usar los métodos replaceState o pushState proporcionados por la clase BrowserHistory para manipular la URL sin recargar la página:

  • pushState: Agrega una nueva entrada al historial del navegador sin recargar la página. Esto es útil para navegar entre diferentes vistas o contenido dinámico.
  • replaceState: Actualiza la entrada actual en el historial del navegador sin agregar una nueva entrada. Esto es ideal para actualizar el estado dentro de la misma vista.

Ejemplo: Actualizando la URL con parámetros de consulta

En este ejemplo, cuando se hace clic en el botón "Actualizar URL", la interfaz de usuario se actualiza para mostrar la categoría seleccionada y el ordenamiento, y la URL se actualiza con nuevos parámetros de consulta para category y sort:

@Route(value = "products")
public class ProductView extends Composite<Div> {
private final Div self = getBoundComponent();
Paragraph paragraph = new Paragraph();
Random random = new Random();

public ProductView() {
Button update = new Button("Update URL", ButtonTheme.PRIMARY);
update.onClick(ev -> {
filter("electronics", String.valueOf(random.nextInt(3) - 1));
});

self.add(update);
self.add(paragraph);
}

public void filter(String category, String sort) {
// actualizar la UI
updateUI(category, sort);

// actualizar la URL
updateUrl(category, sort);
}

private void updateUI(String category, String sort) {
paragraph.setText("Viendo la categoría: " + category + " y ordenando por: " + sort);
}

private void updateUrl(String category, String sort) {
ParametersBag queryParameters = new ParametersBag();
queryParameters.put("category", category);
queryParameters.put("sort", sort);

Location newLocation = new Location("/products?" + queryParameters.getQueryString());
Router.getCurrent().getHistory()
// Actualizar la URL sin recargar la página
.replaceState(null, newLocation);
}
}

Explicación:

  • Método filter: El método maneja la actualización tanto de la UI como de la URL basado en la category y sort seleccionados.
  • Método updateUrl: Este método crea un nuevo ParametersBag para los parámetros de consulta, construye una nueva URL y luego utiliza replaceState para actualizar la URL del navegador sin recargar la página.
  • replaceState: Este método cambia la URL a la nueva ubicación mientras mantiene el estado actual, sin causar una recarga de la página.

Guardando y restaurando el estado en el historial del navegador

Además de actualizar la URL, es posible guardar objetos de estado arbitrarios en el historial del navegador. Esto significa que puedes almacenar datos adicionales relacionados con la vista actual (por ejemplo: entradas de formulario, filtros, etc.) sin incrustarlos directamente en la URL.

Ejemplo: Guardando el estado de selección

En el siguiente ejemplo, una ProfileView consta de varias pestañas (Perfil, Pedidos y Configuración). Cuando el usuario cambia entre pestañas, el estado de la pestaña seleccionada se guarda en el historial del navegador utilizando replaceState. Esto permite a la aplicación recordar la última pestaña activa si el usuario navega de regreso a esta vista o actualiza la página.

@Route(value = "profile")
public class ProfileView extends Composite<Div> implements DidEnterObserver {
private final Div self = getBoundComponent();
TabbedPane sections = new TabbedPane();
int currentSection = 0;

public ProfileView() {
sections.addTab("Profile");
sections.addTab("Orders");
sections.addTab("Settings");

sections.onSelect(ev -> {
currentSection = ev.getTabIndex();
// Guardar el estado usando replaceState
updateState(currentSection);
});

self.add(sections);
}

@Override
public void onDidEnter(DidEnterEvent event, ParametersBag parameters) {
// Intentar recuperar la última sección guardada del estado del historial del navegador
Optional<Integer> lastSavedSection = event.getState(Integer.class);

// Si se guardó una sección, restaurar la selección de la pestaña
lastSavedSection.ifPresent(section -> sections.select(section));
}

private void updateState(int section) {
Router router = Router.getCurrent();
Location currentLocation = router.getHistory().getLocation().get();

// Actualizar el estado actual con la sección seleccionada
Router.getCurrent().getHistory()
.replaceState(section, currentLocation);
}
}

Explicación:

  1. Componente TabbedPane: La vista consta de un componente TabbedPane, que tiene tres pestañas: Perfil, Pedidos y Configuración.
  2. Guardado del estado al cambiar de pestaña: Cada vez que se selecciona una pestaña, el índice de la sección actual se guarda en el historial del navegador utilizando el método replaceState.
  3. Restauración del estado en la navegación: Cuando el usuario navega de regreso a la ProfileView, la aplicación recupera la sección guardada del historial utilizando event.getState() y restaura la selección correcta de la pestaña.