TL;DR:

React-style component development is awesome. But let's not get ahead of ourselves when we start defining new "best practices", by dismissing old techniques and architectures. Let's leverage the work done by super-intelligent people from ecosystems of the recent past. In this case, Adobe Flex.

It’s fashionable to take shots at Adobe and Flash these days, but at one point in pre-HTML5 time, it was a major player in web, mobile, and even native desktop development. There was a period of about 6-8 years where a LOT of supremely-intelligent people, including several authors from EggHead.io, made a very good living contributing their massive brainpower to the Adobe Flash Platform Ecosystem.

We’re now at a point in our industry where whether we want to admit it or not, the “best practices” of old are no longer relevant. Decoupling style, content, state, and interaction does not scale, and we have to start thinking in terms of component systems, not pages. This was what the Flash Platform did, years ago.

Someone is going to unify these three different syntaxes and write a language that just addresses the web platform directly and it’s going to be insanely popular.

-Jeremy Ashkenas

It’s already happening with JSX, but there is still a large amount of room for improvement and fulfilling of that vision. When looking towards the future, it helps to study the past.

In case your’e unfamiliar, Adobe’s Flex SDK was very much like an evolution of the markup + scripting style development platforms like XAML + C#, or today’s JSX + JS. There was a declarative markup language, and a scripting language:MXML and ActionScript 3, respectively.

Looking more closely at Angular and React, its easy to see Flex’s influences. Here are some examples:

<s:Button
   id="myButton"
   color="0x9933FF"
   fontSize="15"
   label="Click Me"
/>

Would render to:

flex button

Lots of “CSS-in-JS” solutions have gotten close to this, but not without having to define top-level style reference objects, or enumerate each component’s style props ahead of time.

A quick note about the Flex namespaces

Before we begin, you may be wondering about the namespaces like s mx fx in the upcoming examples. Think of them like Android versions—something akin to:

<jb:Button>

// or

<ics:TabList>

where jb represents ‘Jelly Bean’, and ics represents ‘Ice Cream Sandwich’. In Flex, s stood for ‘Spark’, and mx, well, it stood for ‘mx’. That was just the name. It was most likely a reference to Macromedia, the company Adobe bought at the end of 2005, which offered the Macromedia Studio MX product suite.

The unique one is fx, which you can think of like the HTML meta tag: not displayed, used for document data, etc.. OK, now that’s out of the way. Let’s dive in.

Style property binding via lookups

Out of the box, Flex could bind style properties between components. For example: 

<s:Panel id="mainPanel">
  // children
</s:Panel>

<s:Button width={mainPanel.width} />

This was years before “responsive design” was even a thing, mind you.

Declarative, state-based style property bindings

You could also bind styles to only appear in certain states. In order to do that, you would define view states declaratively.

<!-- Define the view states.
        The <s:states> tag can also be a child tag of the root tag of a custom component.
-->
<s:states>
  <s:State name="PreLoginState"/>
  <s:State name="AuthorizationState"/>
  <s:State name="LoggedInState"/>
</s:states>

Then, you could set attributes on your component that would bind their appearance to a particular view state.

<s:Button id="button1" />
<s:Button id="button2" includeIn="AuthorizationState"/>

In this case, button2 would not appear on first render, because PreLoginState was defined first, and would be the default view state.

Similarly, you could also use the excludeFrom attribute to prevent rendering inside a given state.

<s:Button id="button3" excludeFrom="PreLoginState"/>

If you had enough view states, you could group them as well.

<s:states>
  <s:State
  name="PreLoginState"
  stateGroups="preAuthStateGroup"/>
<s:State name="AuthorizationState"/>
<s:State
   name="LoggedInState"
   stateGroups="postAuthStateGroup,
   adminAuthStateGroup"/>
</s:states>

The usage was the same as if you were referencing a State name.

<s:Button id="button1  includeIn="preAuthStateGroup" />
<s:Button id="button2" includeIn="postAuthStateGroup"/>
<s:Button id="button3" excludeFrom="adminAuthStateGroup"/>

Dynamically changing a component’s state was also a predefined method you could call on an instance.

<s:Button
   label="Default"
   click="currentState='postAuthStateGroup'"/>

This became more useful when you started listing more states as members of a group.


<s:State
   name="LoggedInState"
   stateGroups="postAuthStateGroup, adminAuthStateGroup"/>

It was even possible to declare the individual values of style properties within each state, facilitating granular, declarative state-based style property declarations.

<s:Panel
  x="0" y="110"
  x.preAuthStateGroup="0" y.preAuthStateGroup="0"
  x.postAuthStateGroup="110" y.postAuthStateGroup="20"
  width.preAuthStateGroup="100" height.preAuthStateGroup="100"
  width.postAuthStateGroup="200" height.postAuthStateGroup="210"
  click="currentState='adminAuthStateGroup'"
/>

State-based content

It went even further, where content and state were able to have defined relationships. The two main public methods of the State class were enterState and exitState. You could use them to conditionally set the content of a given component.

<s:State name="preLoginState"
         enterState="messageArea.text = 'Not yet logged in';"
         exitState="messageArea.text = 'Logging in...';"


<s:Button label="Change to default view state"
            click="currentState='authorizationState';"/>

<s:TextArea id="messageArea"/>

You could also use these state and property definitions in Transitions, much like ReactCSSTransitionGroup, ng-animate in Angular, and others. This one was a little more complicated, so I’ll link to the docs if you’d like to dig in.

Namespaced CSS

CSS Namespaces are ways to define custom styles based on an XML representation of the possible elements your DTD defines—SVG and XUL, for example.

Here’s how it was done for MXML, using CSS Namespaces. The same technique‘drop the hyphen, capitalize the following letter’— needed to be followed here as well because ActionScript was also based on ECMAScript.

<fx:Style>
  @namespace s "library://ns.adobe.com/flex/spark";

   s|Button {
      fontSize: 15;
      color: #9933FF;
    }
</fx:Style>

Many new UI libraries like Polymer, React, Vue, Riot, etc. let you define custom elements. However, since they are transpiled into standard HTML, you aren’t able to easily style based on the displayName you came up with. For example, it would be super handy to be able to write something like:

TabList: {
  background-color: blue;
}

Using CSS namespacing in Flex was defined by package structure. Notice the xmlns:comps="myComponents.*" package namespace declaration.

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:comps="myComponents.*">

    <fx:Style>
        @namespace comps "myComponents.*";

        comps|MyButton {
            color:green;
        }
    </fx:Style>

    <comps:MyButton label="Click Me"/>
</s:Application>

Projects like React-CSS-Components are enabling this today without messing with XML/CSS namespacing. What’s very exciting is that you are also able to define custom variants as CSS pseudo-classes to be exposed as props.

/* CSS */
Label {
  color: red;
}

Label:emphasis {
  font-weight: bold;
}
// JS
<Label variant={emphasis: true} />

// sets both classes with `color` and `font-weight`

Taking it even further, you’re able to go in the other direction, setting variant values based on props.

Label:prop(mode == "emphasis") {
  font-weight: bold;
}
<Label mode="emphasis" />
// sets both classes with `color` and `font-weight`

It compiles down standard HTML and CSS, using CSS Modules (!) to scope the names locally. This is a great improvement to CSS Modules.

import {Label} from './styles.react.css'

<Label />
// => <div className="<autogenerated classname>">...</div>

ItemRenderers

A current “best practice” in React component architecture is to build “Container components”, which are essentially View Controllers in OOP/MVC speak. Flex provided an easy way to customize rendering with ItemRenderer classes.

<fx:Style>
  @namespace s "library://ns.adobe.com/flex/spark";

  s|ItemRenderer { fontSize: 17px,
                   fontStyle: italic,
                   rollOverColor : green }
</fx:Style>

<s:SkinnableDataContainer
   itemRenderer="myComponents.MySimpleCustomItemRenderer">

  <s:layout>
     <s:VerticalLayout/>
  </s:layout>

  <mx:ArrayList>
      <fx:String>Bill Smith</fx:String>
      <fx:String>Dave Jones</fx:String>
      <fx:String>Mary Davis</fx:String>
      <fx:String>Debbie Cooper</fx:String>
  </mx:ArrayList>
</s:SkinnableDataContainer>

This would result in each item having a green background and 17px italicized text when hovered.

Flex custom ItemRenderer

Getting closer with Radium

Projects like Radium are making tremendous strides by providing “higher-order components” as wrappers to React components, which is really just wrapping the render() method, optionally via a Decorator.

@Radium
class Button extends React.Component {
  // ...
}

Flex/AS3 used Decorators as well, albeit with a slightly different syntax.

[Bindable]
public class TextAreaFontControl extends TextArea {}

// or

[Inspectable(defaultValue=true)]
public var shortNames:Boolean = true;

For styles, Flex had a set of classes in the mx.styles package—the main being the Singleton StyleManager. Think of it like a statically-typed virtual CSSOM. Its only parent class was the root Object, which we’ll discuss when we get to the Caveats section below.

The StyleManager class could get/set/remove style declarations, load/unload StyleSheets at runtime, bind styles between components, and more. In the Flex SDK source, style properties that aren’t inherited are defined and enumerated like so:

[Style(name="accentColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

In ES2016 syntax, it would look more like this:

@Style(name="accentColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")

Like this previous Decorator example, Radium provides modifier methods of styling based on props or state, just like React Native. This includes other components’ state. However, the syntax isn’t nearly as nice as it was in MXML.

<button key="keyForButton" style={[styles.button]}>Hover me!</button>
    {Radium.getState(this.state, 'keyForButton', ':hover') ? (
      <span>{' '}Hovering!</span>
    ) : null}

We need something better than ternary operators for UI state display logic. Why not abstract that away like in MXML?

<s:Button
   id="primaryBtn"
   label="Set Style"
   click="setNewStyles()"
   rollOverColor="blue"
/>

// or

primaryBtn.setStyle('fontWeight', 'bold');

If we could sugar markup to allow for this sort of declarative styling, as well as combine the expressiveness of something like React-CSS-Components with the power of Radium, we would be getting closer to reaching the declarative styling bar set by Adobe Flex.

Declarative Custom Methods

Form validation

Anyone who has worked with HTML forms knows the pain of validation. When implementing input validation in Flex, you could write a custom validator or use one of the built-in Validator classes.

See the following example for a built-in Validator.

<fx:Declarations>
   <mx:ZipCodeValidator
       id="zipV"
       source="{myZip}"
       property="text"/>
</fx:Declarations>

<s:TextInput id="myZip"/>

If you wanted to make your own, it was easy*.

<fx:Declarations>
        <MyComp:AgeValidator id="ageV"
            required="true"
            source="{birthYear}"
            property="text" />
</fx:Declarations>

<s:Form >
   <s:FormItem label="Enter birth year: ">
   <s:TextInput id="birthYear"/>
   </s:FormItem>
   <s:FormItem label="Enter birth year: ">
       <s:Button label="Submit"/>
   </s:FormItem>
</s:Form>

How nice would it be to have an input component declare its validator or have a custom validator/inputmode automatically assigned, based on a granular type?

<Input type="{locale}.zipCode" />

String formatting

Flex also had a set of components used specifically for declaration of string manipulation and formatting.

 <s:DateTimeFormatter
    id="DateDisplay1"
    dateTimePattern="MMMM d, yyyy" />

 <s:Label
    id="myTA1"
    text="{DateDisplay1.format(today)}" />

This also made input validation easier, and more dynamic.

<fx:Declarations>
        <!-- Declare and define parameters for the NumberFormatter.-->
        <s:NumberFormatter id="PrepForDisplay"
            fractionalDigits="3"
            decimalSeparator="."
            groupingSeparator=","
            useGrouping="true"
            negativeNumberFormat="0"
            errorText="'{bigNumber.text}' is an invalid input value"/>
</fx:Declarations>

<!-- String to format.-->
  <s:TextInput id="bigNumber" text="Enter number"/>
  <s:Button label="Format Value"
        click="button2_clickHandler(event);"/>

The caveats

The majority of these things could probably be ported in just about any UI framework. However, the way the Flex framework was built goes against what many consider “best practices” in component building.

Flex was an Object-Oriented, inherited, Interface-bound library.

Almost every class had several parent classes, all tracing back to the innermost, base-level Object class (as all ECMAScript languages do). As an example, let’s look at the class inheritance hierarchy of the Alert component:

Alert component class ancestry

That depth of polymorphism also meant that with the creation of every child class came the inherited private, public, and protected methods and properties. That’s a lot of overhead adding up over time.

*Another example: The custom Validator example above is made “easy” if you extend a built-in Validator class.

Performance and progressive-enhancement weren’t really a primary focus

You could feature detect based on Flash Player version, and almost everything had a progress loader, but at the end of the day, we were writing for a specific platform. The debate rages over whether or not the “Web web” is a “platform”.

Every component had its own state

The React community strongly pushes “stateless” components, which again, are just the rendered UI views. In this approach, Flex components each lived in a defined state. As such, this might cause some headaches and overhead management that may not be worth it in terms of costs-to-benefits ratio.