react-hot-toast icon indicating copy to clipboard operation
react-hot-toast copied to clipboard

Calling toast.promise() in componentDidMount()

Open rrikesh opened this issue 4 years ago • 5 comments

Hi, I'm having an issue using toast.promise() and I can't figure out what's wrong with my code. The loading toast doesn't get displayed at all. The success/error toasts appear after the fetch is complete, all good here.

Weirdly, if I uncomment the toast("Hey") (see code below) in the render function, then the loading toast is displayed too (there's also a number that appears on top of the page).

Steps to reproduce on a fresh React install:

  1. npx create-react-app toaster-example
  2. cd toaster-example
  3. npm install react-hot-toast
  4. Use the following code in src/App.js:
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import toast, { Toaster } from "react-hot-toast";

const notify = () => toast("Here is your toast.");

class App extends React.Component {
  componentDidMount() {
    console.log("mounted");

    // Random API from https://github.com/public-apis/public-apis
    const fetchPromise = fetch(`https://randomfox.ca/floof/`);
    toast.promise(fetchPromise, {
      loading: "Loading",
      success: "Got the data",
      error: "Error when fetching",
    });
  }
  render() {
    return (
      <div className="App">
        {/* {toast("Hey")} */}
        <Toaster />
        <header className="App-header">
          <button onClick={notify}>Make me a toast</button>
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
    );
  }
}

export default App;

Thanks

rrikesh avatar Mar 07 '21 06:03 rrikesh

Update:

It seems that no toast loads in componentDidMount on initial page load, but if you hot reload the page after making an edit to App.js, the toast will then appear.

import React, { Component } from "react";
import toast, { Toaster } from "react-hot-toast";

class App extends Component {
 componentDidMount() {
   console.log("mounted");
   // Won't be displayed on page load
   let toastID = toast.loading("Loading toast");
   console.log(toastID);
 }
 render() {
   return (
     <div>
       <Toaster />
     </div>
   );
 }
}

export default App;

However, it is working when I'm using the useEffect hook:

import React, { useEffect } from "react";
import toast, { Toaster } from "react-hot-toast";

function App() {
  useEffect(() => {
    console.log("mounted");
    // Now being displayed
    let toastID = toast.loading("Loading toast");
    console.log(toastID);
  }, []);

  return (
    <div>
      <Toaster />
    </div>
  );
}

export default App;

Do you have any idea of the cause of the issue?

rrikesh avatar Mar 10 '21 06:03 rrikesh

I have same issue.

ksoze84 avatar Aug 19 '21 16:08 ksoze84

I ended up having a acceptable workaround for this.

I put <Toaster /> at ReactDOM.render level:

ReactDOM.render(
  <React.StrictMode>
    <App />
    <Toaster />
  </React.StrictMode>,
  document.getElementById('root')
);

ksoze84 avatar Aug 19 '21 16:08 ksoze84

The toast won't show on the first page load in useEffect when I'm using toast(), until I add setTimeout:

  useEffect(() => {
    const timeout = setTimeout(() => {
      toast(<span>My toast</span>);
    });
    return () => clearTimeout(timeout);
  }, []);

ADTC avatar Feb 08 '23 14:02 ADTC