Home > other >  If success - reset state (promise based toaster)
If success - reset state (promise based toaster)

Time:08-14

Got a form to submit a POST CRUD operation, with data save in a MySql. I use react-hot-toast. Can anybody advise how to reset form's inputs on success? with simple toast i can do just .then(...) and i'm good, but there is a delay, no loading information. So i use promise based example. And now i have no idea how to setState("") if success, if error then do not clear. Or i could have a loading button and simple toast, but then again no idea how to sync them, or how to know data was written to update that button.

const onFormSubmit = async (e) => {
    e.preventDefault()
    try {
      const body = {
        title, //state - controlled input values
        content,
      }
      toast.promise(
        fetch('/api/post', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(body),
        }),
        {
          loading: 'Saving...',
          success: <b>Published!</b>,
          error: <b>Could not save.</b>,
        }
      )
      //  .then(() => {
      //    setTitle('')
      //    setContent('')
      //  })  
    } catch (error) {
      notifyNotOk()
    }
  }

CodePudding user response:

I think chaining the fetch promise in the toast.promise parameter list should work.

toast.promise(
  fetch(...).then(res => {
    if (res.ok) {
      // success, reset form  inputs
    }
  }),
  {...}
)

CodePudding user response:

As per documentation: success and error do accept either Renderable, either function with 1 parameter (data or error) which should return Renderable. So here is an example:

import { useState } from "react";
import toast, { Toaster } from "react-hot-toast";
import "./styles.css";

export default function App() {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");

  const onFormSubmit = async (e) => {
    e.preventDefault();
    try {
      const body = { title, content };
      toast.promise(
        // fetchWrapped(....
        fetch("/api/post", {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify(body)
        }),
        {
          loading: "Saving...",
          success: (data) => {
            setTitle("");
            setContent("");
            return <b>Published!</b>;
          },
          error: (err) => {
            return <b>Could not save.</b>;
          }
        }
      );
    } catch (error) {
      //notifyNotOk();
    }
  };

  return (
    <div className="App">
      <form onSubmit={onFormSubmit}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <input
          type="text"
          value={content}
          onChange={(e) => setContent(e.target.value)}
        />
        <button type="submit">Submit</button>
      </form>

      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <Toaster />
    </div>
  );
}

Now about bad part. Looks like "react-hot-toast" is not handling promises from fetch in a correct way. So in my case (and your original code also) for failed requests "success" will be returned. Issue on the github: Edit fancy-silence-e08uip

  • Related