Giter Club home page Giter Club logo

Comments (27)

uxdxdev avatar uxdxdev commented on September 26, 2024 13

I struggled a bit using toast with React hooks, but got it working like this. Inside your function component call toast in a useEffect hook.

  const [toastMessage, setToastMessage] = useState(undefined);
  const toast = useToast();

  useEffect(() => {
    if (toastMessage) {
      const { title, body } = toastMessage;

      toast({
        title,
        description: body,
        status: 'success',
        duration: 9000,
        isClosable: true
      });
    }
  }, [toastMessage, toast]);

The useEffect hook will only run when the state toastMessage is updated. You will need to then add a message to the toastMessage state for it to fire.

...
setToastMessage(message);
...

I was using event handlers to fire a toast which didn't work as expected for me, it was causing the useEffect hook to fire multiple times which was then registering and then unregistering the listener multiple times. This way worked fine for me.

EDIT: This is not using typescript. This example fixed a strange behaviour for me when using the useToast() hook in an event listener, which I'm thinking now was in a nested function. https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

from chakra-ui.

saferugdev avatar saferugdev commented on September 26, 2024 10

My implementation. Hope it saves anybody some time. Took me 3 days to figure out.

Toast.jsx:

import { useToast } from "@chakra-ui/react";
import { useState, useEffect } from "react";

export function useToastHook() {
  const [state, setState] = useState(undefined);
  const toast = useToast();

  useEffect(() => {
    if (state) {
      const { message, status } = state;

      toast({
        title: status,
        description: message,
        status: status,
        duration: 9000,
        position: "top",
        isClosable: true,
      });
    }
  }, [state, toast]);

  return [state, setState];
}

Where ever you want to create a toast from:

import { useToastHook } from "../components/Toast";

const App = () => {
  const [state, newToast] = useToastHook();

  const someThingHappens = (message) => {
    newToast({ message: message, status: "error" });
  };

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

from chakra-ui.

mattrothenberg avatar mattrothenberg commented on September 26, 2024 3

@beautifwhale I'm struggling to see how that code snippet would compile in a Typescript environment, given you aren't satisfying the definition of the exported useToast function.

This also seems like an oddly oblique way of triggering a toast... The beauty of the useToast hook is that you can create a single instance and call it imperatively in a function – no need for the declarative dance with useEffect. Just my $.02, though!

from chakra-ui.

jason-shen avatar jason-shen commented on September 26, 2024 2

AFAIK, there's no imperative API with which to do this. I'd also throw out there that it feels weird to dismiss a toast imperatively?

One hack that you might be able to employ is using a custom render function for your toast, and adding a ref to the close button inside of it. Then, you can call ref.current.click() to simulate clicking the close button, effectively imperatively closing the toast 👇

// pseudo-code
const closeToastButtonRef = React.useRef<HTMLButtonElement>(null);

const handleImperativeClose = () => {
  if (closeToastButtonRef.current) {
    closeToastButtonRef.current.click();
  }
};

return (
<Button
  onClick={() =>
    toast({
      title: "Account created.",
      description: "We've created your account for you.",
      status: "success",
      duration: null,
      isClosable: true,
      render: ({ onClose }) => (
        <Box m={3} color="white" p={3} bg="blue.500">
          Hello World
          <Button ref={closeToastButtonRef} onClick={onClose}>
            On Close
          </Button>
        </Box>
      ),
    })
  }
>
)

cheers for that, this is a huge help, as this is like something should be add it i think, as the toast is useful for alot of other things

from chakra-ui.

mattrothenberg avatar mattrothenberg commented on September 26, 2024 1

@IsaacGHoward Hit me up via email or twitter, I'd be happy to help you out with this!

from chakra-ui.

ljosberinn avatar ljosberinn commented on September 26, 2024 1

Yeah sorry for that @jason-shen, also cc @mattrothenberg - closing manually is already possible if you keep track of the toastId, see here: https://codesandbox.io/s/stupefied-glitter-2note?file=/src/App.tsx

There is also .closeAll and .update.

from chakra-ui.

mattrothenberg avatar mattrothenberg commented on September 26, 2024 1

Thanks @ljosberinn. We should probably update the docs accordingly? This functionality seems pretty undiscoverable, currently. The type definitions ought to be updated, too. I can take a stab at that.

from chakra-ui.

ljosberinn avatar ljosberinn commented on September 26, 2024 1

Absolutely! That'd be great. :)

from chakra-ui.

ljosberinn avatar ljosberinn commented on September 26, 2024 1

The sandbox uses the latest rc of v1 - behaviour for that has been there for a while already though. Not sure if its in v0.8.

from chakra-ui.

gborges0727 avatar gborges0727 commented on September 26, 2024 1

I had to change a couple things with the above to get it to compile in .ts (notably return as const and add the missing toast var in useEffect):

import { useToast } from "@chakra-ui/react";
import { useState, useEffect } from "react";

type ToastState = {
  message: string;
  description?: string;
  status: "info" | "warning" | "success" | "error";
  position?: "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
};

export function useToastHook() {
  const [state, setState] = useState<ToastState>({
    message: "",
    status: "info",
  });
  const toast = useToast();

  useEffect(() => {
    if (state) {
      const { message, description, status, position } = state;

      toast({
        title: message,
        description: description,
        status: status,
        duration: 2500,
        position: position || "top",
        isClosable: true,
      });
    }
  }, [state, toast]);

  return [state, setState] as const;
}

from chakra-ui.

lee-reinhardt avatar lee-reinhardt commented on September 26, 2024

Can you provide a minimal code example of how you're trying to use it? You can fork the CodeSandbox I linked in the previous issue, or just paste the code here.

from chakra-ui.

mattrothenberg avatar mattrothenberg commented on September 26, 2024

@lee-reinhardt I can't speak for @IsaacGHoward, but I can reproduce a similar issue. Seems like the useToast hook expects args?

Expected 1-2 arguments, but got 0.  TS2554

    29 | 
    30 | const SubmissionFormContainer: React.FC = () => {
  > 31 |   const toast = useToast();
       |                 ^
    32 |   const { mutate } = useMutation(submitFormAction);
    33 | 
    34 |   const handleSubmit = async (values: SubmissionValues, actions: FormikActions<SubmissionValues>) => {

It's a long shot, but is useToast being exported properly here?

Screen Shot 2019-09-10 at 7 49 37 PM

from chakra-ui.

lee-reinhardt avatar lee-reinhardt commented on September 26, 2024

@mattrothenberg Yeah, looks like packages/chakra-ui/src/Toast/index.d.ts has the wrong default export.

@IsaacGHoward Here is a CodeSandbox with a working example

Two things to note about this though:

  • I think the way CodeSandbox does HMR causes it to break if you make any edits, so you have to manually refresh the little browser window to ensure it works again. I do not experience this in a "real" local app.
  • Note how the toast hook is not in the root App component. The useToast() hook needs to be called from a descendant component of the <ThemeProvider />.

Hope that helps.

from chakra-ui.

uxdxdev avatar uxdxdev commented on September 26, 2024

I'm struggling to see how that code snippet would compile in a Typescript environment, given you aren't satisfying the definition of the exported useToast function.

The example is not for Typescript. 👍

This also seems like an oddly oblique way of triggering a toast...

Yes it is, but was needed for the problem I was having. 👍

from chakra-ui.

IsaacGHoward avatar IsaacGHoward commented on September 26, 2024

@mattrothenberg Yeah, looks like packages/chakra-ui/src/Toast/index.d.ts has the wrong default export.

@IsaacGHoward Here is a CodeSandbox with a working example

Two things to note about this though:

  • I think the way CodeSandbox does HMR causes it to break if you make any edits, so you have to manually refresh the little browser window to ensure it works again. I do not experience this in a "real" local app.
  • Note how the toast hook is not in the root App component. The useToast() hook needs to be called from a descendant component of the <ThemeProvider />.

Hope that helps.

Yeah that worked fine for me. My problem I guess is, how do I implement a toast popping up when like, a fetch gives me a certain result? I can't make hook calls from the fetch so what do I do? I don't want a button that will make the toast go.

from chakra-ui.

IsaacGHoward avatar IsaacGHoward commented on September 26, 2024

@IsaacGHoward Hit me up via email or twitter, I'd be happy to help you out with this!

Emailed you, thank you

from chakra-ui.

jason-shen avatar jason-shen commented on September 26, 2024

how do we close the toast manually with code?

thanks

from chakra-ui.

mattrothenberg avatar mattrothenberg commented on September 26, 2024

@jason-shen Can you elaborate on your use case in a new issue?

from chakra-ui.

jason-shen avatar jason-shen commented on September 26, 2024

@jason-shen Can you elaborate on your use case in a new issue?

Basically how u close the toast programally in a function

from chakra-ui.

mattrothenberg avatar mattrothenberg commented on September 26, 2024

AFAIK, there's no imperative API with which to do this. I'd also throw out there that it feels weird to dismiss a toast imperatively?

One hack that you might be able to employ is using a custom render function for your toast, and adding a ref to the close button inside of it. Then, you can call ref.current.click() to simulate clicking the close button, effectively imperatively closing the toast 👇

// pseudo-code
const closeToastButtonRef = React.useRef<HTMLButtonElement>(null);

const handleImperativeClose = () => {
  if (closeToastButtonRef.current) {
    closeToastButtonRef.current.click();
  }
};

return (
<Button
  onClick={() =>
    toast({
      title: "Account created.",
      description: "We've created your account for you.",
      status: "success",
      duration: null,
      isClosable: true,
      render: ({ onClose }) => (
        <Box m={3} color="white" p={3} bg="blue.500">
          Hello World
          <Button ref={closeToastButtonRef} onClick={onClose}>
            On Close
          </Button>
        </Box>
      ),
    })
  }
>
)

from chakra-ui.

jason-shen avatar jason-shen commented on September 26, 2024

see #1723 :)

thanks for that, that is really cool, but still don't show how the user can close manually

from chakra-ui.

jason-shen avatar jason-shen commented on September 26, 2024

Yeah sorry for that @jason-shen, also cc @mattrothenberg - closing manually is already possible if you keep track of the toastId, see here: https://codesandbox.io/s/stupefied-glitter-2note?file=/src/App.tsx

There is also .closeAll and .update.

Thanks for that, thats awesome 👌 thank you again

from chakra-ui.

jason-shen avatar jason-shen commented on September 26, 2024

Yeah sorry for that @jason-shen, also cc @mattrothenberg - closing manually is already possible if you keep track of the toastId, see here: https://codesandbox.io/s/stupefied-glitter-2note?file=/src/App.tsx

There is also .closeAll and .update.

sorry what version of chakra-ui is need it fo this function

from chakra-ui.

with-heart avatar with-heart commented on September 26, 2024

It does not exist in v0.8 unfortunately.

from chakra-ui.

jdbbdj avatar jdbbdj commented on September 26, 2024

My implementation. Hope it saves anybody some time. Took me 3 days to figure out.

Toast.jsx:

import { useToast } from "@chakra-ui/react";
import { useState, useEffect } from "react";

export function useToastHook() {
  const [state, setState] = useState(undefined);
  const toast = useToast();

  useEffect(() => {
    if (state) {
      const { message, status } = state;

      toast({
        title: status,
        description: message,
        status: status,
        duration: 9000,
        position: "top",
        isClosable: true,
      });
    }
  }, [state, toast]);

  return [state, setState];
}

Where ever you want to create a toast from:

import { useToastHook } from "../components/Toast";

const App = () => {
  const [state, newToast] = useToastHook();

  const someThingHappens = (message) => {
    newToast({ message: message, status: "error" });
  };

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

Thanks for this bro! here is how I implemented it

Mother Component where I setup the useToastHook
dispatch(userLogin(values, newToast))

await APICall(
dispatch,
axios.post(${BASE_URL}/auth/login, user),
USER_LOGIN,
callback
)
where the props passed is the user and newToast as callback

on the custom APICall function for axios just call it on the catch(err){
callback({ message: 'Something went wrong', status: 'error' })
}
You can set the message to error.response.data.message

from chakra-ui.

WhooperDar avatar WhooperDar commented on September 26, 2024

My implementation. Hope it saves anybody some time. Took me 3 days to figure out.

Toast.jsx:

import { useToast } from "@chakra-ui/react";
import { useState, useEffect } from "react";

export function useToastHook() {
  const [state, setState] = useState(undefined);
  const toast = useToast();

  useEffect(() => {
    if (state) {
      const { message, status } = state;

      toast({
        title: status,
        description: message,
        status: status,
        duration: 9000,
        position: "top",
        isClosable: true,
      });
    }
  }, [state, toast]);

  return [state, setState];
}

Where ever you want to create a toast from:

import { useToastHook } from "../components/Toast";

const App = () => {
  const [state, newToast] = useToastHook();

  const someThingHappens = (message) => {
    newToast({ message: message, status: "error" });
  };

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

Can anyone have this with typescript?

from chakra-ui.

nimishjn avatar nimishjn commented on September 26, 2024

@WhooperDar There you go

Can anyone have this with typescript?

import { useToast } from "@chakra-ui/react";
import { useState, useEffect } from "react";

type ToastState = {
	message: string;
	description?: string;
	status: "info" | "warning" | "success" | "error";
	position?: "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
};

export function useToastHook() {
	const [state, setState] = useState<ToastState>({
		message: "",
		status: "info",
	});
	const toast = useToast();

	useEffect(() => {
		if (state) {
			const { message, description, status, position } = state;

			toast({
				title: message,
				description: description,
				status: status,
				duration: 2500,
				position: position || "top",
				isClosable: true,
			});
		}
	}, [state]);

	return [state, setState];
}

from chakra-ui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.