FunctionalJS Dojo: A reactive Twitter client
In this dojo, we are going to build a small Twitter client using the reactive loop pattern.
Our client will display a live feed of tweets with simple filtering abilities. It will also asynchronously highlight semantic entities (places, people, etc) and allow adding tweets to a “pinned” list.
First install the dependencies (you have NodeJS, right?):
$ npm install
Then start the local file server:
$ npm run start
Optionally, you can also run the
watch script separately to get
$ npm run watch
app.js file in your favourite editor.
- The code is written in ES6, if anything is unclear check the docs or ask questions!
- Constants or functions whose name ends in
tweets$) denote observable streams, as a convention.
1. Live feed
Let's start by displaying a live stream of tweets in the Timeline.
You can see in the
view function that we call the
function to get a stream of tweets (Note: each element in the stream
is an Array of tweets, not a single tweet!). This stream is passed
columnsComponent, which itself passes it to the
First, replace the dummy definition of
tweetList$ with one that
TODO [#1a]). This should make tweets
appear under your Timeline.
Then, refactor the
tweetElement function to use the more complete
TODO [#2b]). This should make tweets look nicer as in
the screenshot above.
2. Feed filters
At the top of the page, a form (
filtersComponent) is displayed with
two input fields:
- A filter query
- An option to exclude @-replies
The components export their respective models as streams (
exclReplies$). These are also references in the main
function under constants of the same name.
Change the dummy definition of
filteredTweets$ in the main
function to apply the
exclReplies$ filters (see
TODO [#2]). Once done, you should see the Timeline change when using the
3. Pinned column
We want to be able to pin any tweet from the Timeline by clicking it. Pinned tweets should appear in the Pinned column, most recently added first.
First, in the
columnComponent, let's update the
view$ function to
push the tweet object of any tweet element clicked onto the
activate$ stream (see
TODO [#3a]). This is exposed as the
activate$ extent, which for the timeline is translated to the
intent on the
pinnedTweets$ in terms of the
pin$ intent (see
TODO [#3b]). Once completed, clicking a tweet in the Timeline column
should make it appear in the Pinned column.
Then, update the
pinnedTweets$ definition to also include the
unpin$ intent (see
TODO [#3c]). Once completed, clicking a tweet
in the Pinned columns will make it disappear.
4. Entities highlighting
Real web hipsters are also semantic nerds (believe me). So let's highlight semantic entities in the tweets, using an external API to do the entity extraction.
analyseEntities$ takes a string and returns a list of entities
asynchronously, as a stream. Call this function on each tweet before
rendering it (see
TODO [#4a]). Then pass the returned entities as
second parameter to the
tweetElement function and use them to
highlight the words in the tweet (see
5. Drag to pin
mouseup events as streams to
allow dragging tweets from the Timeline to the Pinned column to pin
I've not actually tried that one, so good luck :-)