I recently rewrote my blog website from scratch in Gatsby. This time, I didn’t use a starter template, so I had to make a lot of design decisions. When I wrote the bio section on the home page, initially I put a long heading there as a one-sentence introduction. As I was gazing at the screen, I felt something was wrong. It was too wordy. But after I took out a few words, I was not satisfied with what was left.
After some trying, I came up with an idea. Why not add a typewriter to present more contents with less space? It also adds a lot of fun and dynamic to the page. It seems like legit reasoning, so I did it. I was satisfied at this time.
As I see it, the greatest power of RxJS is that it enables you to encode time in values. Time becomes tangible and can be mixed and matched with other values. In the movie Arrival, an alien language can encode time in itself, so the speaker of that language is capable of foreseeing the future. RxJS is similar in a sense. When programming, you’re the dictator of all events, you already knew what will happen before you start. In RxJS, or reactive programming in a broader sense, you can encode future events in a placeholder (I try to avoid ‘variable’ because it may be confusing for beginners) as you declare it.
Think about the typewriter effect. What we really want is to display different texts on the screen over time. For instance, if we want to type ‘hello’ and then delete it, we want the texts delivered to us over time like this:
// typeh---he---hel---hell---hello// pause--------// deletehello---hell---hel---he---h// pause--------
We can tell RxJS, “Hey, this is the word, I want you to slice it up like this and give the pieces back to me over time.”
After we have a clear vision of what we want, let’s do it and write the code!
Start with the basics. We need to type a single word first. It’s easy.
interval source will fire up events as per the speed value we provide in milliseconds. Each time it will emit a number increasingly. When the event occurs, we map the emitted value to characters from the word. The
interval timer will fire indefinitely, but we only take what we want. After passing the limit specified by the
take operator, the timer will stop.
We also need a delete effect. Let’s add a parameter ‘backward’ to the
type function. We slice differently when ‘backward’ is specified.
To combine the type-pause-delete-pause effects together, we need the
concat operator to concatenate 4 event sources (we’ll call them observables from now on)
We type and delete at different speeds. And also pause differently after typing and deleting. For pausing effect, we emit an empty string and delay the event.
ignoreElements operator just ignore emmited values. This is to only encode time itself and discard any values.
Then we move on to type multiple words. Using the
from operator, we can turn an array into an observable, which is a term to describe “values over time”. After this, we know RxJS will feed us the items in the array over time. But how frequently? In what form? We’ll tell RxJS in the pursuing operators.
useObservable is a helper function to turn values emitted from observables into React state.
concatMap to map every word into a new observable and concatenate them. Say we feed RxJS value
[‘hello’, ‘how are you’, ‘bye’ ], in a diagram, it will look like this:
----typeEffect(‘hello’) ----typeEffect(‘how are you’)---typeEffect(‘bye’)---
repeat operator tells RxJS to repeat the source observable forever.
That’s all the code you need to build a typewriter effect!
Here is a fun demo: