es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

No se pueden leer las propiedades de nulo (leyendo ‘defaultPrevented’) en el aviso de Bootstrap 5.

Utilizando un hook personalizado para mostrar y ocultar “toast”, funciona bien cuando se invoca “showToast” en el botón del componente “Toast”, pero cuando uso este hook fuera, es decir, en el botón del componente “App”, obtengo un error.

TypeError
No se pueden leer las propiedades de null (leyendo 'defaultPrevented')
Toast.show
https://izso9.csb.app/node_modules/bootstrap/dist/js/bootstrap.esm.js:3399:19
showToast
/src/useToast.js:11:12
   8 | 
   9 |  const showToast = () => {
  10 |    bsToast = new Toast(myToast, { autohide: true, delay: 1000 });
> 11 |    bsToast.show();
     |           ^
  12 |  };
  13 | 
  14 |  const hideToast = () => {
View compiled

“useToast.js”

import { Toast } from "bootstrap";
import { useRef } from "react";

export default function useToast() {
  const toastRef = useRef();
  let myToast = toastRef.current;
  let bsToast = Toast.getInstance(myToast);

  const showToast = () => {
    bsToast = new Toast(myToast, { autohide: true, delay: 1000 });
    bsToast.show();
  };

  const hideToast = () => {
    bsToast = new Toast(myToast, { autohide: true });
    bsToast.hide();
  };
  return { toastRef, showToast, hideToast };
}

Enlace de CodeSandbox: CODE SANDBOX LINK

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema aquí está en que el toastRef es nulo fuera del componente Toast. Cuando se utiliza el gancho useToast fuera del componente Toast, el valor de toastRef sigue siendo nulo y, por lo tanto, intentar acceder a sus propiedades (como defaultPrevented) dará como resultado el TypeError que estás viendo.

    Para solucionar este problema, podrías modificar el gancho useToast para que devuelva directamente la instancia bsToast en lugar de usar el toastRef. Luego, puedes crear una nueva instancia de Toast en cada componente que lo necesite:

    import { Toast } from "bootstrap";
    
    export default function useToast() {
      const showToast = () => {
        const bsToast = new Toast(document.getElementById("myToast"), {
          autohide: true,
          delay: 1000
        });
        bsToast.show();
      };
    
      const hideToast = () => {
        const bsToast = new Toast(document.getElementById("myToast"), {
          autohide: true
        });
        bsToast.hide();
      };
    
      return { showToast, hideToast };
    }
    

    Luego, en el componente Toast, puedes utilizar el gancho useToast para mostrar y ocultar el toast:

    function Toast() {
      const { showToast, hideToast } = useToast();
    
      return (
        <div classname="position-relative">
          <button onclick="{showToast}">Mostrar Toast</button>
          <div id="myToast" classname="toast position-absolute start-50 translate-middle-x bg-info text-white" role="alert" aria-live="assertive" aria-atomic="true">
            <div classname="toast-header bg-danger text-white">
              <strong classname="mr-auto">Bootstrap 5</strong>
              <button type="button" classname="btn-close" data-bs-dismiss="toast" aria-label="Cerrar" onclick="{hideToast}"></button>
            </div>
            <div classname="toast-body">¡Hola, Mundo! Este es un mensaje de toast.</div>
          </div>
        </div>
      );
    }
    

    Y en el componente App, también puedes utilizar el gancho useToast para mostrar y ocultar el toast:

    function App() {
      const { showToast, hideToast } = useToast();
    
      return (
        <div classname="App">
          <h1>Toast de React usando Bootstrap 5</h1>
          <button onclick="{showToast}">Mostrar Toast</button>
          <button onclick="{hideToast}">Ocultar Toast</button>
        </div>
      );
    }
    

    Con este enfoque, cada componente que necesite mostrar u ocultar el toast crea una nueva instancia del componente Toast utilizando el gancho useToast. Esto asegura que cada componente tenga su propia instancia de Toast y evita el problema de que toastRef sea nulo.

Comments are closed.