timolins / react-hot-toast

Smoking Hot React Notifications 🔥
https://react-hot-toast.com
MIT License
9.47k stars 310 forks source link

Calling toast.promise() in componentDidMount() #57

Open rrikesh opened 3 years ago

rrikesh commented 3 years ago

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 (

{/* {toast("Hey")} */}
logo

Edit src/App.js and save to reload.

Learn React
);

} }

export default App;



Thanks
rrikesh commented 3 years ago

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?

ksoze84 commented 2 years ago

I have same issue.

ksoze84 commented 2 years ago

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')
);
ADTC commented 1 year ago

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);
  }, []);