Comments (27)
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.
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.
@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.
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 aref
to the close button inside of it. Then, you can callref.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.
@IsaacGHoward Hit me up via email or twitter, I'd be happy to help you out with this!
from chakra-ui.
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.
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.
Absolutely! That'd be great. :)
from chakra-ui.
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.
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.
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.
@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?
from chakra-ui.
@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. TheuseToast()
hook needs to be called from a descendant component of the<ThemeProvider />
.
Hope that helps.
from chakra-ui.
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.
@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. TheuseToast()
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 Hit me up via email or twitter, I'd be happy to help you out with this!
Emailed you, thank you
from chakra-ui.
how do we close the toast manually with code?
thanks
from chakra-ui.
@jason-shen Can you elaborate on your use case in a new issue?
from chakra-ui.
@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.
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.
see #1723 :)
thanks for that, that is really cool, but still don't show how the user can close manually
from chakra-ui.
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
Thanks for that, thats awesome 👌 thank you again
from chakra-ui.
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
sorry what version of chakra-ui is need it fo this function
from chakra-ui.
It does not exist in v0.8
unfortunately.
from chakra-ui.
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.
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.
@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)
- Checkbox data-active state stays if clicked while dragging
- Menu's matchWidth is causing position issues HOT 2
- Flex vs. Stack Documentation
- Sometimes when I want to see a component source on the homepage, I get page not found.
- Remove noreferrer attribute from <LinkOverlay isExternal />
- Unable to style Input component
- Menu child components onFocus firing on hover HOT 1
- Chakra CLI tokens command fails when importing something from @fontsource HOT 1
- VisuallyHidden needs prop showOnInteraction
- VisuallyHidden: ctrl+f browser search finds it HOT 2
- Lock scroll on html for modals/drawers
- Theme: Font size for "md" size on Stat component does not work
- NextJS ChakraUI ToastProvider Issue HOT 1
- Use Modals should stop keyboard Propagation in the same way that it does for clicks HOT 1
- Hydrogen + Vite + Remix installation issue
- Excessive CSSStyleSheet instances leaking
- Adding Hover Effect on Social Icons if Footer in website
- Number Input Custom Format and Parsing - the suffix/prefix is included in parsing HOT 2
- Accessing the useSteps methods gives an unbound-method error
- Default options for toast is not applied.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from chakra-ui.