Skip to content

Instantly share code, notes, and snippets.

@SyNeto
Created May 23, 2025 05:21
Show Gist options
  • Save SyNeto/9b4d96b7cbf0a3d4c7419fa6509fcb2f to your computer and use it in GitHub Desktop.
Save SyNeto/9b4d96b7cbf0a3d4c7419fa6509fcb2f to your computer and use it in GitHub Desktop.

Uso Declarativo de RxJS con useEffect en React

🌟 Objetivo

Integrar programación reactiva (RxJS/Observables) en componentes de React de forma declarativa y reutilizable, permitiendo:

  • Suscripción automática con useEffect
  • Encapsulamiento de lógica en una función utilitaria (useObservable)
  • Desuscripción automática al desmontar el componente
  • Integración sencilla con Firebase Auth o cualquier otro observable

🧱 Hook Reutilizable useObservable

import { useEffect } from 'react';
import { Observable, Subscription } from 'rxjs';

export function useObservable<T>(
  observable$: Observable<T>,
  next: (value: T) => void,
  deps: any[] = []
) {
  useEffect(() => {
    const subscription: Subscription = observable$.subscribe({
      next,
      error: (err) => console.error('Observable error:', err),
    });

    return () => subscription.unsubscribe();
  }, deps);
}

🔧 Integración con Firebase Auth

1. Crear un observable a partir de onAuthStateChanged

import { Observable } from 'rxjs';
import { onAuthStateChanged } from 'firebase/auth';

function authStateObservable(auth: any): Observable<any> {
  return new Observable((subscriber) => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      subscriber.next(user);
    });

    return unsubscribe;
  });
}

2. Usarlo dentro de un componente

import { useState } from 'react';
import { auth } from './firebase';
import { useObservable } from './useObservable';

function MyComponent() {
  const [user, setUser] = useState(null);

  const observable$ = authStateObservable(auth);

  useObservable(observable$, setUser, []);

  return (
    <div>
      {user ? <p>Logged in as {user.email}</p> : <p>Not logged in</p>}
    </div>
  );
}

🧐 Bonus: Composición de Observables

Puedes usar operadores como combineLatest, switchMap, etc.

import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';

const combined$ = combineLatest([observable1$, observable2$]).pipe(
  map(([a, b]) => ({ a, b })),
);

useObservable(combined$, (data) => {
  // manejar el nuevo estado combinado
}, []);

✅ Ventajas del Enfoque

  • Reutilizable: el hook sirve con cualquier observable
  • Declarativo: el componente solo declara la fuente y qué hacer con los datos
  • Seguro: el unsubscribe se maneja automáticamente
  • Escalable: permite componer múltiples fuentes de datos reactivas fácilmente

📝 ¿Extensión futura?

Este hook podría ampliarse para incluir:

  • Estados loading, error
  • Soporte para operadores comunes (filter, debounceTime, etc.)
  • Integración con useSyncExternalStore en React 18+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment