I recently implemented a Play application using ReactJS for its frontend (and wrote a post about it). The next step I needed to understand was a nice way to enable communication between components. That’s how I started reading about Flux and a project inspired by it, RefluxJS. I decided to give the latter a try, and here’s how I patched everything together. The full project code is available on GitHub.
First of all, setup a new basic Play application using Activator:
play-scala as starting point and fire up your development tools. I personally favor IntelliJ with the Scala plugin, which allows you to import the project from an external SBT module.
Next, you’ll want to import ReactJS and RefluxJS in your build file. To achieve this, we’ll user WebJars, which are client-side libraries packaged into JAR files in order to be easily included in any JVM based project. They are available on Maven and therefore accessible via most build tools such as Maven, Gradle or SBT. The first thing you want to do with a view on using WebJars is import the webjars-play helper library in your
I found it very helpful as it allows you to dynamically locate the libraries you will import. To use this feature, you need to add a new line to your
At this point we’re ready to import ReactJS and RefluxJS in our
build.sbt file. As simple as adding
plugins.sbt in your
project folder and add
Go back to
build.sbt and enable the
SbtWeb plugin by adding it next to the Play plugin:
Note: after changes in
plugins.sbt, you most likely need to reload the project; the simplest way is to use the
reload command from the sbt console. Otherwise, just close and rebuild the project from command line (that is, launch
activator in the project folder and then
Our setup is now complete - we can start reacting and refluxing!
Create your own view in the
views package or modify the existing
index.scala.html. Whichever way you choose, add the
reflux.js libraries. It should look like this:
.fullpath call in the
react inclusion. This is needed as there are two instances of
react.js in the React library, so we need to specify its position to the locator; see this question on StackOverflow. As my personal advice, use single quotes in the
<script> tags; double quotes might mess up your paths.
I often find online tutorials and examples that end up building quite complex stuff. I chose the simplest example that came to my mind: two buttons and a string telling you which button has been clicked.
Action object. Let’s implement our first Action.
In your Play project structure, create a subfolder of
assets. Under that, create another subfolder
actions. Check the repo if you want to be sure. In the
actions folder, we can create our action file, call it
Action object can contain multiple listenable labels, but in our case it will be only one:
The entities that listen to the actions are called Stores. Under
stores and in it the file
clickedStore.js. Its content:
Let’s check what’s happening here. We’re instructing this store to listen to the
ClickedAction set of actions. Such set contains only one action, named
clicked. Here, we create a function with the same name, that takes one parameter
n. Inside this function, we invoke the method
trigger, passing the parameter
n. It will all make sense when we see the main React file and the Reflux wiring magic in action (pun not intended).
There are three main components here:
Button: displays a button with a text and a number (coming from its props), and upon clicked triggers the
clicked“label” of the
ClickedActionAction, passing its number. This resolves in the store being notified.
Info: a component that simply shows a text indicating which button has been clicked last. This is where some of the Reflux magic happens: by creating the mixin connecting the store with an arbitrary label that will end up being part of our component’s state. This is achieved with the
Reflux.connect(ClickedStore, 'clickedStoreHappening'). We effectively linked this component to the store listening to the ClickedAction actions. We give this link with the
clickedStoreHappeninglabel, but it could be anything. As a result, this label will be part of the state of this component. When the store gets notified of the ClickedAction.clicked, it will
trigger(n), and that
nwill end up in the state of the linked component (
Info), a render will be triggered and the value of
nwill be available through
ButtonPage: simple component that displays together buttons and the info text.
The file you have just created needs to be referenced in your HTML file, after the content div. Also, you will need to include the two files about the ClickedAction and ClickedStore:
Run the project (
activator run in the project folder) and point your browser to
http://localhost:9000. You’ll see how the main info is re-rendered every time you click on a button.
I know, it all feels very magic, but I think this is much better than the old mess of callbacks we were used to. Let me know if you experiment further with this.