Displaying Rails flash messages with React

Rails has a nice and useful mechanism to communicate to user via flash messages. By default these messages come from backend and are injected into the page while rendering the view.

But what if we want to show a client side message ? Or, for example, we did an unsuccessful Ajax request and want to warn user using a message in response. If you already use React in your project then you will find it as a good candidate to handle this.

The project sample is on Github.

Tooling

Implementation

First what we would have to do is to implement Alert React component that could display a message using Bootstrap alerts:

app/assets/javascripts/components/alert.es6.jsx

As there might be multiple flash messages at once, we need to implement another React component that could display list of alerts. Let’s name it FlashMessages:

FlashMessages component is also a component where the state should live and it wraps a list of Alerts into a div tag.

Our React components are ready to use, so we can put them to the pages. First we would define a small application helper to convert Rails flash messages to the structure our React component expects it:

app/helpers/application_helper.rb

And now we can add react components to the pages using react_component helper in application template:

app/views/layouts/application.html.erb

So now Rails flash messages could be displayed using React. Nice. But two things need to be clarified:

  • How to add new messages from client side ?
  • Because we plan to add messages from client side, it would be nice to automatically hide older messages on timeout and unmount appropriate React components, wouldn’t it be ?

To achieve this we can slightly modify our components:

app/assets/javascripts/components/alert.es6.jsx

Now Alert component accepts onClose callback and defines two new methods: componentDidMount and componentWillUnmount . These methods are used to set/clear timer to call onClose callback. That’s it, after some period of time the component is going to be unmounted automatically.

Also now, the button to close an alert will call onClose callback if being clicked instead of a data-dismiss: 'alert' . This will let React to fully control the component. The process of dismissal was controlled by DOM itself.

Another small addition is type checking (propTypes) and default properties (defaultProps) that makes our component much more sensitive.

app/assets/javascripts/components/flash_messages.es6.jsx

FlashMessages component is modified in the following way:

  • In constructor we have saved a reference to this React component into a global variable. After a component being rendered, we can easily add a new message on client side:
  • New methods addMessage and removeMessage to add a message to the list and remove it. Both use update addon to change the collection.
  • List of alerts are now wrapped into CSSTransitionGroup to make some css animation. According the docs the animation itself has to defined using css transitions. So here it is:
app/assets/stylesheets/messages.scss

This transition is really very similar to fade in and slide up effect. And the coolest thing is that now we have the same effect if we close alert manually or it is closed after a timeout:

Wrap up

It the article we found a pretty way to display Rails flash messages using React components. For this we created Alert and FlashMessages components and wrote a little of css for fade in and slide up effect.

This gives us a nicely looking and powerful mechanism to consistently talk to user from server side and client side as well.