Finishing Up


Right now we have some good things, and some bad things. Addressing the bad things should make the good things even better. So let's keep going.

The main bad things are:

  • using setInterval inside our render method
  • not using the output of this.determineNextColourCombo()
  • we're not applying the CSS changes anywhere anyway

Let's start with the big issue: using setInterval inside our render method.

The React docs give us a better approach to this problem.

Let's use the React component lifecycle approach to address this issue:

+   public componentDidMount() {
+       this.interval = setInterval(() => this.updateGradient(), 1000);
+   }
+
+   public componentWillUnmount() {
+       clearInterval(this.interval);
+   }

    public render() {
        this.determineNextColourCombo();
-       setInterval(this.updateGradient.bind(this),2000);

        return (
            <div className="AnimatedBackground">
                hello
            </div>
        );
    }

TypeScript isn't happy about us using this undefined interval property.

Now, this property doesn't need to be on the state in my opinion. It's a purely internal concept. I'm going to define a private class property for this instead.

private interval: any;

Wrap Up And Display

All the hard work is now done.

What we now need is the two interesting RGB values, which we can then use to create the next background attribute to apply to our div.

    public render() {
        const nextColourCombo = this.determineNextColourCombo();

        const css = {
            background:"-moz-linear-gradient(left, "+nextColourCombo[0]+" 0%, "+nextColourCombo[1]+" 100%)"
        };

        return (
            <div className="AnimatedBackground" style={css}>hello</div>
        );
    }

Two Bugs

There are, unfortunately, two rather pesky little bugs to contend with.

The cause of the first is something of a guess. Here's the code:

        this.setState({
            step: step + gradientSpeed
        });
        console.log('step',step );

        if ( this.state.step >= 1 )
        {
            // etc

I believe, but am not sure how to reliably evidence, that using this.state.step after previously changing the state of step with this.setState is the cause of the problem.

We can fix this bug by using the destructured step rather than this.state.step in the conditional:

-       if ( this.state.step >= 1 )
+       if ( step >= 1 )
        {

And that seems to fix that.

The second bug is a bit more tricky.

Watch the video for a better understanding of the exact problem. It's a visual thing. We see a 'flicker' when the conditional is triggered.

Again, my solution to this is a guess as to why this works.

        if ( step >= 1 )
        {
-           this.setState({
-               step: step % 1
-           });

            this.state.colourIndices[0] = this.state.colourIndices[1];
            this.state.colourIndices[2] = this.state.colourIndices[3];

            // pick two new target colour indices
            // do not pick the same as the current one
            this.state.colourIndices[1] = ( this.state.colourIndices[1] + Math.floor( 1 + Math.random() * (colours.length - 1))) % colours.length;
            this.state.colourIndices[3] = ( this.state.colourIndices[3] + Math.floor( 1 + Math.random() * (colours.length - 1))) % colours.length;

+           this.setState({
+               step: step % 1
+           });
        }

Simply moving the second update of the component's state to after the logic has been evaluated 'fixes' the problem. My best guess here is that there's a momentary delay - the flicker - whilst the rest of the computation happens.

By shifting the second call of this.setState to after the logic is evaluated, we get a much smoother experience.

And that's it. We have migrated Mario Klingemann's code to TypeScript.

As mentioned right at the start of this tutorial, a possibly preferable solution to this problem is to use CSS3 transitions / animations instead. That said, I hope you found this process useful, and that you fall in love with TypeScript, as I have.

Code For This Course

Get the code for this course.

Code For This Video

Get the code for this video.

Episodes

# Title Duration
1 Super Mario 12:09
2 How, and Why 17:06
3 Finishing Up 06:10