A common kind of “global” data is a toast or popup notification that appears in the corner of the app when some event happens. Allowing a deeply-nested component to surface a notification using props can be painful, but Context makes it much easier. In this lesson we’ll see how to dispatch a notification from a deeply-nested component and display it at the root level.
Instructor: [00:00] The app is set up right now to fetch emails every five seconds. Let's display a pop-up notification when new emails arrive. To do that, we'll make a new file called notificationContext.js. In here, we'll import react, create a new context, and destructure that context into provider and consumer.
[00:19] Then we'll make a class called notificationProvider, and this'll have a bit of state, which we'll initialize with an empty array of messages. Then in render, we'll use the provider to render out a wrapper div. Inside here, we're going to put a list of notifications and the component's children at the bottom.
[00:38] Inside the list, we'll map over messages, and for each message, render a notification, passing in the required key prop, set to the message's unique ID and the message itself, and onClose prop that'll call this.removeMessage with the message.
[00:58] We also want to pass the value prop to the provider, passing in all of the existing state, and the notify function, which will be this.addMessage. We have to implement a couple of these things. We'll start with the notification component at the bottom.
[01:14] It'll take message and onClose, and it's going to render out a list item. In here, we'll display messageText and button with an X. We'll pass our onClose function as its onClick prop. Now, we can write the addMessage function.
[01:30] It'll take the text and set the state based on the existing state, returning a new object with messages equal to a new array that contains all of the old messages, plus a new object with an ID that's a random number, the text, and the time this message was added.
[01:49] Then we'll write the removeMessage function, which is going to take a message, and then update the state. We'll set messages to the existing messages, but filtered, only keeping the messages that are not the one we want to remove.
[02:06] At the bottom, we'll export the notification provider and consumer as the notifier. Then we can go back over to email provider. What we'd like to be able to do is emit a notification from here after the state is set.
[02:21] The way the consumer works, if we use that notifier component here, we won't have any way of getting the notify function out to where we needed to call it. We'll go back over to notificationContext. We'll make a function called withNotifier.
[02:35] This is our higher order component, and it's going to take a component. It's going to return a new component that takes some props. Inside here, we'll use the consumer and the renderProps pattern to pull out the notify function, and render out the component, passing in the existing props and our notify callback.
[02:56] Now, we can export withNotifier down here, and then emailContext the top. Import withNotifier and notificationContext. Now, at the bottom, we need to wrap this email provider with the higher order component.
[03:11] Since we can't dynamically export this by wrapping it with notifier, we can create a variable called wrapped, and call withNotifier on the email provider. Then we'll export this wrapped this as the email provider.
[03:25] Now, we're getting this error because we're not using the notification provider anywhere. Let's open up the index file, at the top, we're going to import notification provider. Down at the bottom, we can wrap everything with this notification provider.
[03:44] Now, we can go back over to emailContext, and right after we set the state with the new emails, we'll call this.props.notify, which we now have available. We'll pass in a message to display. Now, whenever emails arrive, we get a notification, and we can click the X to dismiss them.
FYI: The 'before' code for this lesson is here if you need it.
how ugly this is? very ugly, everything it's a provider?!?! just DON'T! don't use context anymore
That’s just how I chose to organize the code here, to show how it could be split up. Feel free to combine them though!
You could merge the providers together into one Global provider (e.g. one provider holding state for emails, notifications, and user), or alternatively create a “wrapper” Provider which wraps its props.children with all 3 other providers.
that sounds better, I haven't experienced yet this, but an example would help others too, I guess
componentWillUnmount is not working on NotificationProvider class. Notifications still shows on logout.
I'm really enjoying this course so far, thanks Dave!
Hello there, Thanks for the great content, I learned a bunch! Here, maybe like Leox noted above, the notifications popup on the login page, which seems sort of out-of-place. Is this an out-of-scope issue for this video series, to make the notifications show-up only on the email-list page?