Vue & React lifecycle method comparison

🤔 This is a slightly older post. It deals with Vue 2 and React class components. This is probably not what you need if you’re building a new app today.

React and Vue both have fairly well defined lifecycle events which we can use to successfully navigate the mysteries of the virtual DOM.

So without further ado, let’s get down to the React vs Vue lifecycle events smackdown!

Vue and React fighting in an animated fashion. A caption reads "Bam!"

Vue lifecycle events visualised

The following demo logs out the Vue lifecycle events when a component mounts and updates.

It’s actually a fairly nice API in that everything is consistently named, even if not all of the events are strictly useful.

Vue lifecycle events on codepen

React lifecycle events visualised

React is actually the more esoteric of the two in terms of naming, but actually offers more powerful functionality (such as my particular favourite, shouldComponentUpdate).

Vue lifecycle events on codepen

Component mount compared

The basic workflow for a component is pre-mount → render → mount.

Vue has more events, whereas React is more Javascripty with an actual ES constructor.

ReactVueDescription
constructorbeforeCreateRoughly synonymous with each other. The constructor sets up the React class, whereas Vue handles the class creation for you.
dataSet data. Vue recursively converts these properties into getter/setters to make them “reactive”.
createdData observation, computed properties, methods, watch/event callbacks have been set up.
beforeMountRight before the mounting begins: the render function is about to be called for the first time.
getDerivedStateFromPropsInvoked right before calling the render method. It should return an object to update the state, or null to update nothing.
renderrenderThe virtual DOM is rendered and inserted into the actual DOM.
componentDidMountmountedThe component is now mounted. We can make any direct DOM manipulations at this point.

We can see from our lifecycle that the perfect time to hook into the process is once the component has been mounted (in React’s componentDidMount or Vue’s mounted event).

Component update compared

Component update generally follows a pre-update → render → updated workflow. Easy!

ReactVue 
getDerivedStateFromPropsSame as when mounting.
shouldComponentUpdateLet React know if a component’s output is not affected by the current change in state or props. We can use this to prevent React blowing away our changes.
beforeUpdateCalled when data changes, before the DOM is patched.
renderrenderThe virtual DOM is rendered and patched into the actual DOM.
getSnapshotBeforeUpdateRight before the most recently rendered output is committed to the DOM. Lets you save the previous state of the DOM for use after the component has updated.
componentDidUpdateupdatedAfter the DOM has been updated

Component unmount compared

When your component is removed from the page, sometimes you need to remove event handlers or clean up after any manual DOM manipulation.

ReactVueDescription
deactivatedWhen using Vue keep-alive, the component is removed from the page but not destroyed so that we can load it again later without the overhead of component mount.
activatedThe previously deactivated component is reactivated.
componentWillUnmountbeforeDestroyWhen a component is being removed from the DOM
destroyedThe component is completely gone.

Handling errors

This is something I’ve not looked too much into, but it’s possible to catch errors from child components and change the render accordingly.

This would be most useful for a top-level component (above the routes, maybe) to show an “Aw Snap” error message into your app and stop the error bubbling up.

ReactVueDescription
componentDidCatch
getDerivedStateFromError
errorCapturedAn error occurred in a child component.

Conclusion

Each has their own benefits, neither is objectively better or worse. Personally I prefer the Vue naming, but prefer the power of the React API.

After pulling this info together I’m really interested to try out Vue’s keep-alive for render-intensive jobs. It’s a cool feature I didn’t know existed.

I’m also excited to play with component-level error handling, especially for larger apps. It makes a lot of sense to catch errors in the framework rather than waiting for them to bubble up to the global error handler 😅

Anyway, hope this was helpful. I learned something.

My Twitter ad blocking experiment, DOM manipulation in someone else’s React app

Twitter as a platform is pretty neat. Twitter as a company… has its problems.

A while back they started showing ads into my timeline, which is something I'm really not here for. I would gladly pay a fee not to have that because I love the platform, but y'know. Corporate bullshit 🙄

So I've been taking it out on the advertisers audacious enough to target me, by blocking them. Apple? Blocked. Amazon? Blocked. Intel? You betcha you're gonna git blocked.


Despite my best efforts it got to the point where I was getting way too many ads to keep up with, so I decided to write a script to do it automatically.

TL/DR: I just want to install the ad blocker extension

There's an extension you can install to auto-block Twitter advertisers (providing you're using the mobile site). You can get this for:

Update 2019: I've taken it down because it stopped working.

Automating actions in someone else's react site 🤔

I mainly use the mobile Twitter site because it's way faster than desktop, but it's one of those sites that use post processing to munge class names. So instead of seeing nice
<div class="tweet"> HTML, you get something more akin to <div class="rn-1oszu61 rn-1efd50x rn-14skgim rn-rull8r []…]">

This makes it insanely difficult to automate the process of finding an ad and
blocking it. I'm not sure what ad blockers are doing, but this requires some
pretty specific DOM selection to get working.

There's two approaches you could take:

  1. Loop through all the <div> elements on the page until you find one with the
    text you're looking for. Eg. "promoted".
  2. Use weirdly specific selectors that get the job done, almost by chance.

Despite making fun on Twitter I chose the latter, because Twitter uses inline SVG elements, which means we can find promoted tweets by querying for the presence of certain SVG paths. It's completely absurd and I think React is criminally negligent for making this a standard practice.

Here's the two main selectors I'm using to find interface elements on Twitter mobile:

// The "promoted icon"
const adSelector =
  'path[d="M20.75 2H3.25A2.25 2.25 0 0 0 1 4.25v15.5A2.25 2.25 0 0 0 3.25 22h17.5A2.25 2.25 0 0 0 23 19.75V4.25A2.25 2.25 0 0 0 20.75 2zM17.5 13.504a.875.875 0 1 1-1.75-.001V9.967l-7.547 7.546a.875.875 0 0 1-1.238-1.238l7.547-7.547h-3.54a.876.876 0 0 1 .001-1.751h5.65c.483 0 .875.39.875.874v5.65z"]';

// The dropdown chevron
const dropdownSelector =
  'path[d="M20.207 7.043a1 1 0 0 0-1.414 0L12 13.836 5.207 7.043a1 1 0 0 0-1.414 1.414l7.5 7.5a.996.996 0 0 0 1.414 0l7.5-7.5a1 1 0 0 0 0-1.414z"]';

The remainder of the extension is fairly straightforward. Find stuff, click stuff, you know the deal. If you're interested in having a play with it yourself, you can check it out and give it some stars on Github.

Dates & Formatting in Javascript


Dates and Javascript haven't traditionally been very nice. The
Date object
is the only real API for managing dates and code to deal with it can be extremely verbose.

Parsing dates with Javascript

Parsing dates has traditionally been difficult with the Date object only supporting non-standardised inputs dependent on the browser:

RFC 2822
Sat Apr 12 2014 12:22:00 GMT+1000
Unix timestamp
1397269320000

But with ECMAScript 5 we can also parse ISO 8601 dates, which gives us a little more leeway. From the MDN date docs:

simplified extended ISO format (ISO 8601) is always 24 or 27 characters long
(YYYY-MM-DDTHH:mm:ss.sssZ or ±YYYYYY-MM-DDTHH:mm:ss.sssZ, respectively). The timezone is always zero UTC offset, as denoted by the suffix "Z".

To parse a date in plain Javascript, you can now pass a well formed ISO8601 string to the constructor:

var dIso = new Date('2014-04-12T12:22:00.000+10:00');
var dRfc = new Date('Sat Apr 12 2014 12:22:00 GMT+1000');
var dUnix = new Date(1397269320000);

All the above will all return a valid date. Note that the Unix timestamp is in milliseconds. If you're trying to read a Unix timestamp in seconds you may need to multiply it by 1000.

Update: Turns out Safari is a laggard with ISO 8601 dates and like IE8, can't parse them at all. If you need ISO8601 dates on the client, you'll have to resort to either a custom solution or something like moment.js which supports parsing them.

Formatting dates in Javascript

The problem of formatting dates in a particular way in Javascript is difficult. If you wanted to print a basic YYYY-MM-DD timestamp you could do something like the following, but you'd also have to implement logic around padding zeroes and incrementing the zero-based month and the syntax for the most basic notation is horrible. It's no fun.

var d = new Date();
return d.getYear() + '-' + (d.getMonth+1) + '-' + d.getDay();
// 2014-4-12

One of the better libraries for managing dates in Javascript is Moment.js, which brings slick chainable date handling to the browser (or node). The main downfall is that it’s quite heavy, but when you need to be able to manipulate a lot of dates it’s totally worth it.

Our previous example can be condensed into the following:

return moment().format('YYYY-MM-DD');

Moment has some other sweet features, particularly around date parsing and manipulation so you should definitely check it out.

Specific date formats in JS and Moment

While we're at it, here's a cheat sheet of specific date formats you may need to use in JS.

Date Raw JS Moment
RFC 2822 myDate.toUTCString() moment().format('ddd, DD MMM YYYY HH:mm:ss ZZ')
ISO 8601 myDate.toISOString()* moment().toISOString()
Unix Timestamp Number(myDate) moment().valueOf()

Note that the native Date.toISOString method was introduced in ECMAScript 5, so only works in IE 9 and above.

Isometric Tile Transforms

It might require a bit of initial thinking, but I'm sure it would be worth it.

I’m debating with myself whether to make my game engine pseudo-3D, using transforms and masks and whatnot to generate and texture isometric tiles.

On one hand there’s something to be said for tile-based systems to have every graphic meticulously crafted by a master designer, but on the other hand, I’m not that designer. It’d be so much easier to slap a grass texture down and transform it to match a programmatic grid. Maybe adjust the brightness to simulate lighting, then cache that sucker to achieve decent performance and move on to the next tile.

I think it’s feasible. It would allow for much easier creation of game elements such as hills and height, walls, roads, and so many more cool things. It’s also a total departure from my original idea of a traditional isometric game engine, but once it’s implemented it would make things way easier for both myself and anyone who wanted to create a map in the future because one high resolution texture could be used for countless tile combinations.

I think I’m going to give it a try, because if nothing else it’s a damn cool idea.

SVG and Canvas Transformation Matricies

Both SVG and HTML5 Canvas have basic transformations such as rotation and scaling, but they also have a more advanced “transformation matrix” mode which lets you do more complex transformations. I’m not pretending to understand it properly.

A transformation matrix has six parameters, named A—F. A lot of the documentation I found on them wasn’t particularly useful, so here’s my take on how each value works:

NameDescriptionDefault ValueExplanation
awidth11 equals 100%. A value of -1 would mirror image the object on the left hand side. .5 would halve the width, and 2 would double it, etc.
bY axis shear0A positive value shears the object downward on the righthand edge.
cX axis shear0A positive value shears the object rightward on the bottom edge.
dheight1Similar in operation to a, above.
ex offset0Offset the object on the x axis.
fy offset0Offset the object on the y axis.

So for instance, if you wanted to create an isometric tile from an image, you could use the following transform:

matrix(1,-.5,1,.5,0,0)

This would keep the same width, shear both axis by 50% effectively rotating the image 45°, and halve the height giving us our iconic half-height isometric tile.

Some other transformations relevant to isometric game tiles might might include:

OperationOutput
matrix(1,0,0,1,0,0)No change.
matrix(1,-.5,1,.5,0,0)Square sheared into half-height isometric tile.
matrix(1,-1,1,.5,0,0)Sheared into a leftwards isometric incline.
matrix(1,1,-1,.5,0,0)Sheared into a rightwards isometric incline.
matrix(1,0,1,.5,0,0)Sheared into a leftwards isometric decline.
matrix(1,0,-1,.5,0,0)Sheared into a rightwards isometric decline.

You’ll notice that the output tiles are significantly larger than would be generated with a straight out rotate and scale. You may need to add an additional scale operation to adjust the size of these tiles to fit your game board.

Putting it Together

Once you put these tiles together, you start to get an idea of how we can use canvas (or SVG) matricies to create isometric tiles for your game.

Using transforms to create game images makes tiles click into place like lego.

If you wanted to play around with transforms with a visual tool, you could check out Inkscape, the best vector editor in the world. The matrix transformation sidebar is found by clicking the menus Object , Transform, then clicking the “Matrix” tab.