React.js, Flux, Om: I am trying to think it through

(My notes on some of the idea behind React, Flux, OM, etc., as I understand them)

First, lets remember that react.js is supposed to the view layer. With it, we define the UI through a component hierarchy. It can re-render the DOM fast and easily. We re-render when our application data/state changes. This leaves the M and C parts of MVC. Where does our application logic live, and where does your application data live? In thinking this through and comparing approaches, I found it helpful to consider these two concerns separately).


In standard react.js, you call setState() on any component within the view layer to cause that part of the UI to be re-rendered. Standard react.js doesn’t care how you do your app logic or manage the app data. You can happily add it to the react.js components itself.

Making the react.js components hold your app data as state will break down as soon as one piece of data affects two parts of the UI. Try to move such state up the view hierarchy to a shared component and you will end up in callback-passing hell. So moving the application data out of the react components is an obvious step.

Making the react.js components itself update the application data should get you pretty far, on the other hand, I think. I imagine things can get fiddly if you multiple sources of changes: from user interaction, events streaming from the server.

So if in your react.js component you have a onClickHandler on a button which modifies an external data structure to add a TODO item, how do we tell the “todo list component” to update itself?

  1. I don’t even want to consider building a findComponent(‘list).update().
  2. You can pass the onClick event all the way up to shared component, and implement the logic there. This will involve a lot of painful callback passing/prop transfer code, I think. You could build a system where a single signal object is passed down, and the button can do signal.trigger('add-todo; ), where as the parent view can catch it and act.

  3. You can modify the data at the level of the button, and create a system where changing your application data model triggers a callback where relevant parts of your UI listen to.


Facebook’s Flux defines a concept of Stores to hold your application data. The stores trigger callbacks when the data is changed, and your react.js components can listen to these change events.

Flux moves all application code out of the react.js components. Instead, interactive elements in your view hierarchy fire actions which go through a global dispatcher. Some application code can live in the actions itself (that is, in flux, within the action creator function). Other code lives in the stores: The stores watch for actions being dispatched, and then change the application data that they hold according to the action (then they trigger a callback, which will cause the views to re-render themselves).

In practice, only a couple components (controller views) listen to the store events, and child components get the data from the parents via pops.

In this model, all data that isn’t transient should live in the stores, and the state of the react.js components would at best contain a copy.

Thinking in react explains it very explicitly.


Om decides that since the re-render is so fast, we can just re-render the whole UI whenever anything changes. So rather than having multiple controller-views that listen to different stores, like in Flux, simple have the root listen to all data changes.

Om has a thing called a cursors, which is a view on a subset of the application data. A cursor can change the part of the data it points to, thus triggering a change event on the complete data structure itself, thus causes a full re-render. Components in the hierarchy are generally being given cursors from the parent as a prop.

Om also uses immutable data structures. There are a variety of benefits, but in particular, it can make the re-render a lot faster: by default, a re-render still means recomposing the whole virtualDOM again. To avoid this, react.js has shouldComponentUpdate().


Let’s talk about shouldComponentUpdate(). I found it hard to understand at first why react.js needs this hook. Assuming that I call setState() when the data changes, don’t I always want a re-render? But of course, that is only true if each state is limited to one component. If we talk about a potentially deeply nested data object like in Om, applied to a deeply nested view hierarchy, changing on integer in one branch does not mean we need to re-render the whole tree. (Also, there will be some cases where you call setState()with a “full reset” data object, and you don’t know or care if any of the state has actually changed).

But since react.js already expects you to call setState() manually, why can’t it compare the new state with the old state by itself? Facebook says they don’t trust you to use setState() exclusively, and not accidentally modify the state in-place. If you trust yourself, you should be able to implement a simple shouldComponentUpdate() to do exactly that comparison.

Om further uses immutable data structures. If your application data is immutable, your checks in shouldComponentUpdate() (if the new data is different than the old for any particular component) can simply compare object identity, which is much faster than comparing a deeply nested structure.


What is the better approach? The Flux stores or the Om singleton? It seems to be that they are both similar and completely different things.

Where it comes to your application code, the default thing in OM (and also derivatives like react-cursor) seems to be to put your application code into your components. Modify the data directly via the cursors. This will cause a re-render. But you can easily change this, and use a Flux-like action system in Om to encapsulate the application code.

The actions themselves might change the application data, or you might have multiple stores, which catch the actions, and which would simply be a namespace within the application data structure, that they manage (this idea is described here).

When it comes to the application model part, they seem not so different. I already mentioned that in Flux, you will have only a few controller views which watch for application data changes and pass it down. If you have very few of them, you might only have one, and then you have the single data structure as in Om. So it seems to me like the the difference between one global data structure, and two global data structures (imagine a virtual parent between them, and its the same).

It’s the same with the callbacks from the application data container (i.e. the stores or the Om atom) to the views. The single data structure in Om causes a re-render from one root controller view is just the simplest version of the controller view concept.

I think it is this that the Om author means when he says “Thus we don’t need React operations like setState, which exists to support both efficient subtree updating as well as good object-oriented style”. If you can make the full render fast enough, you don’t need to essentially manually optimize by targeting specific sub-components with change notifications.

A pattern that you arrive at very quickly with Flux is that for a controller view you have a getState() builder function which gets the state from the store, and then you use it in getInitialState and whenever you call setState(). Once you do that, what do you have is conceptually like a cursor to a subset of your application data.

So I think Om might be on to something here.


So in terms of my architecture, it seems I can make a couple of decisions.

Do I need good performance? Then I can either make sure model updates hit far down in the component hierarchy, and write good shouldComponentUpdate() handlers, or I can use immutable data structures, render everything from the top, and my shouldComponentUpdate() will be reliable and fast.

If my app is small, react might be fast enough even when rebuilding the complete Virtual DOM tree.

How do I communicate changes from my data to my views

I can use Flux stores and have callbacks to subcomponents, or I can have what amount to a single store and have callbacks to the top root for a full-render. I think callbacks are pretty much it. One or more parts of your view will listen for callbacks. These callbacks are triggered by your stores/controller code, or if you use a cursor-system, your datastructure already provides the solution.

While in theory possible, I would avoid having your controller code inside your react components to update both the external models and then re-render the view.

Where do I want to write my application code? Where do I affect changes to my data?

If you don’t want your application code to live with your React.js components, something like the Flux system seems natural, meaning, some code will be in action creators, some code will be in the models. I don’t feel like I should to be too dogmatic about it though, and variations on Flux, which is somewhat loosely defined anyway, seem perfectly feasible, too.

If you want to put some of the logic inside your React.js components itself, you can still have stores and call e.g. TodoStore.add() as an accessor, and have some of your logic inside your data models. Or you can use cursors to modify the data directly, and put your code completely into your view components. Sometimes you might communicate with a parent component via props/callbacks (I like the idea of a signal object, see the first section).


Looking at what I wrote, It seems I’m essentially saying “you can do what you want with react”. There are probably various advantages and disadvantages to the different approaches, which I don’t understand yet, but I found this exercise very helpful for myself to understand the role of react.js and how it compares within these different ideas.

The idea of adding application code to the react components itself has a certain appeal to me, because what you end up with is similar to how you might structure, say, an app in Ext.js or Qooddoo, where each component in the view hierarchy is it’s own mini-MVC entity. The react component being the controller and the render() method being the view.

I’m also tempted a lot to use the React component state for anything that might be UI state, which ends with me communicating events up the view tree more than I want.

On the other hand, there is something beautifully simple about the uni-directional dataflow of Flux. The react.js component is only the view, and my code lives in a swarm of actions. It reminds me of MOVE (https://cirw.in/blog/time-to-move-on).

I hate the verbose string comparisons in flux, so I’d look at something like reflux.


There are some links I collected during this.

Some libraries to re-create Om ideas in plain Javascript

[http://www.code-experience.com/why-you-might-not-need-mvc-with-reactjs/](Why you might not need MVC with React.js) It defines the difference between data state and application state, and points out how react, by nature of overwriting the whole DOM you your own tree, requires you to define all state explicitly (it will be overwritten if it’s only in the DOM).

[http://www.code-experience.com/async-requests-with-react-js-and-flux-revisited/](Ajax should be done in action creators, not in stores)

Watching a movie with two subtitles

Tools to merge SRT subtitles

SRTMerger – Input: SRT, Output: SRT, Different colors, displays both subtitles at the bottom, on top of each other.

2srt2ass – Input: SRT, Output: ASS. One subtitle on the top of the screen, one subtitles at the bottom (possible because the output format is ASS).

DualSub – Input: SRT, Output: SRT; displays them at the bottom, next to each other. This is essentially a hack, so it requires you to specify the font with which your player will display the subtitles in advance – you are essentially creating subtitles for a particular player, and it can be a bit fiddly. On the plus side, this one has amazing options for keeping subtitles on the screen for longer, when possible, as well as smoothing over small timestamp differences.

Player functionality

Subtitler (VLC plugin)

Dictionaries, APIs and Databases, in German and other languages

Aside from the obvious, like Wiktionary, Duden, there is also:

Attempts to parse Wiktionary (collected from SO)

Part of Speech tagging

Mail-in-a-box on OpenVZ

  • Use export DISABLE_FIREWALL=1 before running install (I think the firewall can be made to work, but I didn’t attempt it).
  • With ubuntu-14.04-x86_64-minimal, I get this message on container start: resolvconf: Error: /run/resolvconf/interface either does not exist or is not a directory. Subsequently, DNS in the machine doe s not work because /etc/resolv.conf is empty, and any OpenVZ –nameserver options are not applied. This is because mail-in-a-box installs the resolv.conf package, and per /etc/vz/dists/scripts/set_dns.sh, if that package is install, it will be used to set the nameservers. Going through dpkg-reconfigure resolvconf there seem to be a bunch of approaches, though the interworkings of the whole system don’t really understand, but what worked for me was making sure that /etc/resolv.conf is a symlink to /run/resolvconf/resolv.conf, and that /etc/resolvconf/resolv.conf.d/tail contained my nameserver x.x.x.x instruction.

Tools for self-hosted email

I’ve been running my own mail server for years, using the ispmail setup, and recently I have been looking into replacing it with a slightly more comprehensive setup (with a modern webmail, admin ui), ideally without putting in all the manual work. Here is what I came up with:

Open Source options

sovereign – ansible based, lots of unrelated stuff, but no admin ui for mail.

mail in a box

iRedmail – seems capable, but no cool factor.

modoboa – Administration only

Webmail Interfaces

Rainloop

Mailpile

Roundcube, or successor

Interesting Commercial Mail solutions

FastMail – uses Sieve for filters.

atmail – provides a self-install version; a web interface I really like; pricing seems unclear

I forgot the PIN on my Nexus 7, and then I reset the lockscreen using the recovery mode

  • Your device has to be unlocked, otherwise you are out of luck, I believe (who knows, maybe something can be done using ADB debugging only). Note how unlocking your device makes it less secure.
  • Power+VolumeDown until in fastboot mode.
  • fastboot flash recovery recovery-clockwork-6.0.4.3-grouper.img
  • Go to recovery mode without rebooting, which may reset recovery.
  • $ adb shell
  • $ mkdir /mnt/d && mount -t ext4 /dev/block/platform/sdhci-tegra.3/by-name/UDA /mnt/d
  • $ rm /mnt/d/system/locksettings.db*
  • $ reboot

It is probably possible to modify the settings in locksettings.db individually, though it didn’t work for me on first attempt.

Note: When profiles are used, the data for other users can be found in /data/user/.

Generating reports and invoices in the 21th century

When it comes to generating a PDF from a web app, too many people seem to just take FPDF and fiddle with a whole lot of write(x,y) and y+10 calls. Ugh. That is just aweful.

Back when we were writing desktop apps, supposedly there were things like Crystal Reports. There seem to be a couple ones that have things like PHP clients for web usage (and most seem to be able to access a database directly) – Pentaho, Jaspersoft, BIRT.
I don’t have experience with any of them, but when I look at YouTube videos, I see things like “Eclipse” plugins generating pretty ugly looking tables.

I suppose it is perfectly feasible to work with them, though I shy away from the complexity and unsexiness.

There is a thing called FO-XML. It seems like pretty sophisticated stuff, but I’m not about to start learning a new XML language.

It seems there is an opportunity to do this by using HTML and CSS for paged media.

WeasyPrint can render such CSS to PDF. It has some limitations (no markup in page margins), as does the official spec. There are competing extensions to the spec by W3C and WhatWG.

Meanwhile, commercial alternatives to WeasyPrint like PrinceXML (also Antenna House](http://www.antennahouse.com/) have their own custom CSS extensions.

DocRaptor provides PrinceXML as a cloud service.