Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
- Antoine de Saint-Exupery
ViewModel for React is a thin layer on top of React to work with as little boilerplate and ceremonies as possible.
Actually it's pretty simple, you have an object and the view is rendered based on the properties of that object. Want to modify the state of the view? Just modify the object. Want to save the state of the view at any given time? Just save the object somewhere. Want to return the state of the view to what it was? Just load the saved object. Using the buzzword of the day, it's "easy to reason about".
By the way, this isn't anything new or ground breaking. This way of writing applications has been around for a long time (long before React).
Yep, those were simpler times, before Flux, Reflux, Redux, or Delux. A time when you didn't have to know about dispatchers, reducers, transducers, or confusers.
This is for people who like the view model way of developing UIs (think React at the beginning, Angular, Knockout, Aurelia, etc.) but don't like the boilerplate and ceremonies that usually go with those libraries and frameworks.
You'll probably hate this library if you identify with the following statements:
React does less than other frameworks so it's easier to take JSX and build a DSL on top of it (removing all the boilerplate).
I feel like view layers are needlessly bloated and complex. More often than not you're doing things, not because your application requires it, but because the framework does. I like to read and write code relevant to my applications, not a framework. ViewModel is an attempt to eliminate anything that isn't "your code".
Hello({ render() { <label class="label" style="color: blue"> Hello World! </label> } })
ViewModel adds the crust React requires. So our Hello component file gets transpiled into:
import React from 'react'; export class Hello extends React.Component { render() { return ( <label className="label" style={{ color: "blue" }}> Hello World! </label> ); } }
Echo({ message: '', render() { <div> <input b="value: message" placeholder="Type something..." /> <label b="text: message" /> </div> } });
I don't know what definition you've heard but here a binding is only a shortcut for a ceremonious task. There's nothing evil, magical, or mystical about them. Let's take a simple example from JavaScript. You could write the following:
i = i + 2;
Or you could write:
i += 2;
The += assignment operator is analogous to a binding in ViewModel. It's a shortcut and you don't have to use it if you don't want to. Is it wrong to use the += operator? Is it too much "magic"? I don't think so.
Yes. It transpiles the b="" attributes/bindings into idiomatic React code. For example, if you write:
<p b="if: show">Hi</p>
It transpiles into:
{ this.state.show ? <p>Hi</p> : null }
Syntactic sugar is nice but it's far from being what reduces your code the most. It's all the ceremonies, complex patterns, and runarounds you don't have to deal with anymore. To give an example, one of the UI boogeymen is state that is shared between two or more components. The two most common ways of dealing with this situation are:
1) Let components reference one another so they can get the state they need. The problem here is that you want to share a banana but you end up sharing the gorilla holding the banana, and keeping track of the entire gorilla tribe.
2) Store the entire state of the application in a central place. You no longer need to keep track of the gorillas, but now you need a jeep, a machete, and know your way through the entire jungle just to share a banana.
ViewModel takes the simple approach of only sharing the state that needs to be shared. Components don't reference one another, you keep the shared state to a minimum, and components are explicit about which state can be modified by someone else. It works like this:
First define a container for the state that needs to be shared
ViewModel.share({ house: { address: '' } })
In this case the container is 'house' and the state to share is 'address'.
Now you can declare that a component will share the house properties with other components:
ComponentA({ share: 'house', render() { <input b="value: address" /> } })
ComponentB({ share: 'house', render() { <div b="text: address" /> } })
Now components A and B have access to the same address and nothing else. You use them as normal and treat address as just another property of the components.
Of course, ViewModel sits on top of React, so the only thing out the window are the needless ceremonies. You can keep using your stack of choice (Express, .Net Core, Meteor, Feathers, etc.) The same applies to bundlers, plugins, custom components, optimizations, etc.
Of course. The preferred way is to try it with something medium size (a small component might not be worth it, a large one might be too daunting). I think it’s better if you experience it yourself. Take a relatively small part of one of your website (a medium size component) and re-write it using ViewModel.