react-hot-toast
react-hot-toast copied to clipboard
Calling toast.promise() in componentDidMount()
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:
- npx create-react-app toaster-example
- cd toaster-example
- npm install react-hot-toast
- 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
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?
I have same issue.
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')
);
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);
}, []);