LouisBarranqueiro / reapop

:postbox: A simple and customizable React notifications system
https://louisbarranqueiro.github.io/reapop
MIT License
1.55k stars 78 forks source link

Close notification programatically #526

Closed msanandrea closed 1 year ago

msanandrea commented 1 year ago

When I create a loading type notification, I won't use the dismissAfter property as I won't know how much time would I need. Based on this, how can I dismiss the notification from code? My guess would be I should be able to do something like this.

const notification = notify(...); notification.close(); I'm missing something here or this is a feature request?

TobiasGrether commented 1 year ago

Hey there,

I just looked around in the code a bit. While there is no direct support for promises, you should be able to easily integrate that yourself.

    const updatedNotification = () => {
        const notif = dispatch(
            notify({
                id: 'updated-notification',
                title: 'Repository transfer',
                message: 'Your repository is being transfered...',
                position: POSITIONS.topRight,
                status: STATUSES.loading,
                dismissible: false,
                dismissAfter: 0,
            })
        ).payload

        setTimeout(() => {
            notif.status = STATUSES.success
            notif.message = 'Your repository have been transfered.'
            notif.buttons = [{name: 'OK', primary: true}, {name: 'Details'}]
            dispatch(notify(notif))
        }, 3000)
    }

This is taken straight from the Demo code. You could replace the setTimeout() call with a promise.then() to achieve the same result from what I can see,

Kind regards, Tobias Grether

TobiasGrether commented 1 year ago

I wrote this simple typescript code to make it easier to write this without repetition:


declare type NotificationRequestOptions = {
    loading?: {
        title?: string;
        message?: string;
    },
    success?: {
        title?: string;
        message?: string;
        buttons?: NotificationButton[];
    },
    error?: {
        title?: string;
        buttons?: NotificationButton[];
    }
}
export function NotificationRequestHelper<T>(notify: (notification: Partial<Notification>) => Notification, promise: Promise<Response<T>>, options: NotificationRequestOptions): Promise<Response<T>> {
    const notif = notify({
        title: options.loading?.title ?? "",
        message: options.loading?.message ?? "",
        position: POSITIONS.topRight,
        status: STATUSES.loading,
        dismissible: false,
        dismissAfter: 0,
    })

    return promise.then((response) => {
            const {data, error} = response
            if (error) {
                notif.status = STATUSES.error
                notif.title = options.error?.title
                notif.dismissible = true
                notif.dismissAfter = 5 * 1000
                notif.message = error.message
                notif.buttons = options.error?.buttons ?? []
            } else {
                notif.status = STATUSES.success
                notif.title = options.success?.title
                notif.dismissible = true
                notif.dismissAfter = 5 * 1000
                notif.message = options.success?.message
                notif.buttons = options.success?.buttons ?? []
            }

            notify(notif)

            return response
        }
    )
}```
msanandrea commented 1 year ago

Thanks @TobiasGrether ! Even though your solution is good, it's not the exact same thing I'm looking for. It can happen I don't have to use promises and still want to close a previous notification (i.e a chain of events with different messages on each step) preventing the pops to stack.

TobiasGrether commented 1 year ago

Well in that case you can just use setTimeout to achieve the same thing I believe? I reckon using setTimeout and updating the notification to have a dismissAfter of 1 should work?

msanandrea commented 1 year ago

Yup, that works...even though is not the most elegant solution, it works.

Thanks @TobiasGrether !

LouisBarranqueiro commented 1 year ago

👋 @msanandrea Sorry for the very late reply, I was on vacation. Thanks for your help @TobiasGrether. 🙏

const notification = notify(...); notification.close();

Would that work for you?

const notif = dispatch(notify(...)).payload
// when you want to close the notification
dispatch(dismissNotification(notif.id))
LouisBarranqueiro commented 1 year ago

@msanandrea I'm closing this issue as it is inactive. Feel free to re-open it to continue the discussion 🙂