Topic: MDB React - Toast Manager - Dynamically inject toasts without hooks outside of components?

jammerxd2 priority asked 1 year ago


I am seeing the most popular way to dynamically insert toasts is to call toast.info, toast.success, toast.danger, etc... However, this only exists in the react-toastify npm package and doesn't use the MDBToast component. Does MDB React have a similar function that we can use to inject toasts without using hooks, without using contexts so that we can inject a toast from say an API client error handler function?

StatusService.js:

import React from "react";
import { handleResponseError, handleError } from "../ApiClient";
export class StatusService
{
    async getStatus()
    {
        return fetch("/api/v1/State/Status").then(response=>{
            if(!response.ok)
            {
                console.log("ERROR");
                handleResponseError(response);
            }
            return response.json().catch(error=>{
                console.log(response);
                handleError(error);
            })
        });
    }
    }

ApiClient.js:

export function handleResponseError(response)
{
    throw new Error("HTTP error, status = " + response.status);
}
export function handleError(error)
{
    console.log("ERROR");
    console.log(error.message);
}

How do I make the handleError and handleResponseError classes show a toast without having to make each component that calls each api service (there's going to be over 20-30) show the toast themselves (this creates a lot of redundant code and isn't very reusable)?

Since these are outside of react components, there can be no hooks (no contexts, no custom hooks) and because this is React 18, ReactDOM.render is deprecated and can't be used. I tried ReactDOM.createPortal in a render method but that didn't actually do anything to render the list.

This is what I tried with no success: ToastManager.js:

import React from "react";
import ReactDOM from "react-dom";
import { MDBToast } from "mdbreact-ui-kit";


export class ToastManager {
   toasts = [];

   show(options) {
    const toastId = Math.random().toString(36).substr(2, 9);
    const toast = {
      id: toastId,
      ...options, // if id is passed within options, it will overwrite the auto-generated one
      onHide: () => this.destroy(options.id ?? toastId),
    };

    this.toasts = [toast, ...this.toasts];
    this.render();
  }

   destroy(id) {
    this.toasts = this.toasts.filter((toast) => toast.id !== id);
    this.render();
  }

render() {
    console.log("render");
    const element = <>
        {this.toasts.map((toastProps) => {
            return <MDBToast key={toastProps.id} {...toastProps} />
        })}
        </>
        let docId = document.getElementById("toast-container");
        console.log(docId);
    ReactDOM.createPortal(element,document.getElementById("toast-container"));
  }
}

export const toast = new ToastManager();

Mateusz Lazaru staff commented 1 year ago

I don't think it's possible without calling a hook. You'll need to get the response status to the functional component and then create a toast based on the response.



Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Opened

Specification of the issue

  • ForumUser: Priority
  • Premium support: Yes
  • Technology: MDB React
  • MDB Version: MDB5 6.2.0
  • Device: PC
  • Browser: Firefox
  • OS: Windows 11
  • Provided sample code: No
  • Provided link: No