Dramatically simplify your React code

11 Likes

Nice read, got me laughing in the middle :slight_smile: That pretty much explains the ~300% productivity boost Iā€™ve been experiencing lately. Very thankful for having ViewModel.

Out of curiosity, have you tried migrating an app built with the Blaze version of ViewModel to React? It seems like there could almost be an automated tool for it, theyā€™re so similar. Where would the biggest bulk of manual labour be lurking?

1 Like

Iā€™m rewriting the phone book example with viewmodel-react. Itā€™s very easy to translate one to another but I donā€™t think itā€™s worth it to create a converter because there are a lot of non-ViewModel edge cases where Blaze behaves one way and React another. I donā€™t know of anyone who writes 100% idiomatic ViewModel (not even myself) so thereā€™s some translation to do.

While that is certainly nice, the documentation is a bit sparse on the ā€œAnd how do I actually get data in there?ā€ part.

Basically, itā€™s missing quite an important piece of the ā€œModelā€ in ā€œViewModelā€.

Just thought you should know that prior to VM for React, I could not consider even using React as it wasnā€™t quite as productive as what I was able to achieve with Blaze/VM (and productivity is my #1 concern as we are a small team).

Yet the React VM makes it completely viable for my purposes - and sometimes the code actually ends up being even cleaner than the Blaze alternative. So now we are using React for new projects, and we are seriously considering switching over our very large business app to React in the future (which is a big deal - we have not even upgraded for 1.4/import statements/etc yet - not worth our time - so for us to consider this upgrade means a lot!).

Thank you very much for your work!

2 Likes

I need to explain this better in the documentation.

  1. This is just the V in MVC. It has little to do with your DB models. Itā€™s called view-model because itā€™s a pair, the view is rendered based on a model (the ā€œmodel of the viewā€). Itā€™s not the capital M in MVC. For example, if you have the view-model <div b="text: message" /> - { message: "Hello" } then you know the view will render <div>Hello</div>. The view always renders based on its model.

  2. You load data the same way you would with any other view layer. With the old Meteor you can just return the results of a collection in a method. For one time data you populate your collection when the components are created. With something like Horizon/RethinkDB you subscribe to the data stream:

const Horizon = require('@horizon/client');
const horizon = Horizon({ secure: false });
const messagesCollection = horizon('messages');

Messages({
  created() {
    messagesCollection.watch().subscribe(
      (messages) => { this.messages(messages);}
    );
  },
  messages: [],
  render() {
    <div>
      Messages:
      <Message b="repeat: messages" />
    </div>
  }
})

This is on my todo-list :slight_smile:

1 Like

Ah, its that thing!
I think its wonderful, but really, nearly the only reason why people work with React - because everyone does.
Thatā€™s the reason most people are careful about switching into different ā€˜sugarā€™ until its stable and recommended by tons of different manuals and blogsā€¦

Yet, I feel that ViewModel, its documentation and github responses are just insane, I donā€™t remember that much love put into project except redux itself, hence its popularity. Will think about switching to ViewModel again, but anyway, Viewmodel docs and github are pure candy for my exhausted eyes!

2 Likes

And just for that I changed the code samples from Kansas black and white to Technicolor :slight_smile:

Random thoughts (sorry, I have many)ā€¦

I disagree a lot with DHH (who created Ruby on Rails) but I wholeheartedly agree with his sentiment surrounding design decisions or RoR. For example, like RoR, ViewModel optimizes for developer happiness. Whoā€™s happiness? First and foremost, mine. If it sounds selfish, itā€™s because it is. I want to smile when I see my code, and I do smile when I look at something like this:

List({
  colors: ['red', 'green', 'blue'],
  render(){
    <ul>
      <li b="repeat: colors, text: repeatObject, style: { color: repeatObject }" />
    </ul>
  }
})

A lot of people see that and scoff ā€œToo much magic!ā€ā€¦ ViewModel isnā€™t for them.

Some people look at that and they smile with me thinking ā€œThat is the absolute minimum way to express what I want to do.ā€ā€¦ ViewModel is for them.

As long as you donā€™t go down the ā€œMust monkeypatch everything!ā€ route like RoR did :slight_smile:

Because too much magic can make it very difficult to override behaviours when you need to. :wink:

Another question: How well does it play with other React components?

Say, I want to use MaterialUI - Iā€™m seeing bindings for the standard attributes, what about custom ones, like:

   <Dialog
          title="Dialog With Actions"
          actions={actions}
          modal={false}
          open={this.state.open}
          onRequestClose={this.handleClose}
        >

Would I be able to bind, say, title to a ViewModel?

Sure,

Example({
  title: "Dialog With Actions",
  render(){
    <Dialog title={this.title()} />  
  }
})

Although it looks innocuous, {this.title()} starts getting annoying when youā€™re dealing with a lot of attributes (e.g. youā€™re working with SVG). ViewModel has the option of specifying which attributes should be used as binding. Then you can do:

Example({
  title: "Dialog With Actions",
  render(){
    <Dialog b="title: title" />  
  }
})

Is this open source? Where is the source code? I canā€™t find any github link

Amazing the things you forget to include in the docs.


Look like you extracting Tracker from Meteor. Why donā€™t you publish it as separate NPM package?

Last question, is this possible to render HTML directly?

With JSX, we use dangerouslySetInnerHTML which is inconvenient.

It would be great to have a simple example also for meteorā€¦ for noob like me!

I use a copy of Tracker because I removed all Meteor references from it. I donā€™t publish it on NPM because 1) I honestly donā€™t see the point and 2) I donā€™t want to maintain it (be the person who answers questions about Tracker).

As for direct HTML, see https://viewmodel.org/#BindingsHtml

Example({
  message: 'Can it be a <strike>strike</strike>?',
  render() {
    <div>
      <input b="value: message" placeholder="Type something" />
      <label b="html: message" />
    </div>
  }
})

See this thread shows you how to set it up with Meteor: ViewModel for React Alpha

I know that. What I asked, suppose I have input html string:

let html = `<p>I'm html <strong>string</strong></p>`

Can I render that like so:

render() {
  return (
    <div>
    	{html}
    </div>
  )
}

That is exactly what it does.

1 Like