---
title: Introducing React-View-Model — MVVM with React
description: Learn how to follow the Model-View-ViewModel pattern in React with a new package called React-View-Model!
image: https://www.bitovi.com/hubfs/Bitovi_July_2016_Theme/Images/canjs-background-blue.gif
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting)
- ![Project Management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project Management](https://www.bitovi.com/services/agile-project-management-consulting)
- ![Product Design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product Design](https://www.bitovi.com/services/product-design-consulting)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting)
- [Design systems](https://www.bitovi.com/services/axure-figma-migration)
- [React](https://www.bitovi.com/services/frontend/react-consulting)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about delivering products and solving problems.
  
  ](https://www.bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships)
- [![Academy](https://www.bitovi.com/hubfs/icon%20-%20academy%20(4).svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse or contribute to our community
  
  ](https://www.bitovi.com/open-source)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

 September 27, 2017

# Introducing React-View-Model — MVVM with React

 Learn how to follow the Model-View-ViewModel pattern in React with a new package called React-View-Model!

![Chasen Le Hara](https://app.hubspot.com/settings/avatar/47447d7b410651534d079d84497c1a5c)

 Chasen Le Hara

Share:

[![Twitter](https://www.bitovi.com/hubfs/limbo-generated/_astro/twitter-white.os3xLc3C_Z2nW4or.svg) ](https://twitter.com/intent/tweet?text=) [![Reddit](https://www.bitovi.com/hubfs/limbo-generated/imgs/icons/reddit.png) ](http://reddit.com/submit?url=)

At [Bitovi](https://www.bitovi.com/development), we work with [React on lots of client projects](https://www.bitovi.com/frontend-javascript-consulting/react-consulting), and we like its straightforward API and using JSX for templates. Redux is common in the React community, and we know it’s [not the right solution for every project](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367).

For us, Redux doesn’t work well with our development workflow. We build apps as individual [modlets](https://css-tricks.com/key-building-large-javascript-apps-modlet-workflow/) that act as mini apps in and of themselves, that are assembled to make the larger app. Redux’s global store feels more like a [monolithic meatball](https://twitter.com/justinbmeyer/status/908304412669595649) that controls the entire app.

![Picture of meatball with straight spaghetti coming out from it](https://www.bitovi.com/hs-fs/hubfs/monolithic%20meatball.png?width=500&height=500&name=monolithic%20meatball.png)

We believe [independently](https://canjs.com/doc/guides/technical.html#Independent)-[testable](https://canjs.com/doc/guides/technical.html#Testable) ViewModels makes for more maintainable code. Last but not least, implementing lifecycle methods such as `shouldComponentUpdate` in class components feels like a step backward because we’re used to [CanJS intelligently updating the DOM](https://canjs.com/doc/guides/technical.html#MinimalDOMupdates) when necessary.

To solve all of these problems, we decided to bring the best part of CanJS to React: its observables! Using [react-view-model](https://v4.canjs.com/doc/react-view-model.html) lets you create observable ViewModels for React components.

## How to use react-view-model

Let’s look at [an example](https://bitovi-jsbin.jsbin.com/cudobut/2/edit?js,output) of a functional React component that has a ViewModel.

First, we’ll import [can-define](https://canjs.com/doc/can-define.html) to create an observable ViewModel:

```
import DefineMap from 'can-define/map/map';

export const ViewModel = DefineMap.extend({
  count: 'number',
  increment: function() {
    return this.count++;
  },
});
```

Each instance of our `ViewModel` type will have a `count` property and an `increment` method. Notice how this ViewModel type is separate from our component code; we’ll discuss testing this code on its own in a little bit.

Next, we’ll import [react](https://facebook.github.io/react/docs/react-api.html), [react-dom](https://facebook.github.io/react/docs/react-dom.html), and [react-view-model](https://v4.canjs.com/doc/react-view-model.html), then pass [react-view-model](https://v4.canjs.com/doc/react-view-model.html) the `ViewModel` type and a render function that uses the `viewModel` instance passed to it:

```
import ReactDOM from 'react-dom';
import reactViewModel from 'react-view-model';
import { ViewModel } from './view-model.js';

const AppComponent = reactViewModel(ViewModel, (viewModel) => {
  return (
    <div onClick={ () => viewModel.increment() }>
      Count: {viewModel.count} (Click Me)
    </div>
  );
});
```

Lastly, we’ll add our component to the DOM, which will create an instance of the view model and call the render function:

```
ReactDOM.render(
  <AppComponent count={0} />,
  document.body
);
```

With the component rendered to the DOM, we can click on the text and see the count increment. Whenever something that’s bound to in the view-model changes, the render function will be called again.

One of the beautiful things about this pattern is how **our ViewModel is separated from the component** code. This lets React focus on what it’s good at—the View—and give us the opportunity to create nice, testable instances of the ViewModel.

## Testable ViewModels

With our ViewModel code separate from our component code, we can **test it independently and reuse it across components**.

```
import DefineMap from 'can-define/map/map';
import QUnit from 'qunitjs';
import { ViewModel } from './view-model.js';

QUnit.test('ViewModel increment', function( assert ) {
  const viewModel = new ViewModel({count: 1});
  assert.equal(viewModel.count, 1, 'Starting count is correct');
  viewModel.increment();
  assert.equal(viewModel.count, 2, 'Increment works');
});
```

In [the example](https://bitovi-jsbin.jsbin.com/yikayib/9/edit?html,js,output) above, we have the same `ViewModel` as before, and now we can unit test its functionality without having to import React or render our component to the DOM.

## Further reading

We’ve barely scratched the surface of what’s possible when CanJS’s observables are paired with React. The [react-view-model documentation](https://v4.canjs.com/doc/react-view-model.html) has more info about this powerful combination.

Let us know on [Twitter](https://twitter.com/canjs), [Gitter](https://gitter.im/canjs/canjs), or [the CanJS forums](https://forums.donejs.com/c/canjs) if you experiment with this new package. We also do [React consulting](https://www.bitovi.com/frontend-javascript-consulting/react-consulting) and would be happy to help your team with your app or lead a training. We’re excited about the new possibilities and eager to hear about how you’re using them!

[![Tag for open source](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) open source ](https://www.bitovi.com/blog/topic/open-source)[![Tag for development](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) development ](https://www.bitovi.com/blog/topic/development)[![Tag for canjs](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) canjs ](https://www.bitovi.com/blog/topic/canjs)

 Previous Post

![](https://www.bitovi.com/hs-fs/hubfs/plant-growing-through-crack-in-concrete1.jpg?height=117&name=plant-growing-through-crack-in-concrete1.jpg) [ How to Integrate Other Libraries using Symbols ](https://www.bitovi.com/blog/integrate-other-libraries-with-symbols)

  

 Next Post

![banner-blog-gridCSS.jpg](https://www.bitovi.com/hs-fs/hubfs/blogposts/cssgrid/banner-blog-gridCSS.jpg?height=117&name=banner-blog-gridCSS.jpg) [ Using CSS Grid to Build a Page Layout with a Sticky Header and Footer ](https://www.bitovi.com/blog/using-css-grid-to-build-a-page-layout)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/introducing-react-view-model-mvvm-with-react",
    "@type" : "WebPage",
    "description" : "Learn how to follow the Model-View-ViewModel pattern in React with a new package called React-View-Model!"
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Chasen Le Hara"
  },
  "dateModified" : "November 27, 2018, 7:01:03 PM",
  "datePublished" : "2017-09-27 17:25:53",
  "description" : "Learn how to follow the Model-View-ViewModel pattern in React with a new package called React-View-Model!",
  "headline" : "Introducing React-View-Model — MVVM with React",
  "image" : {
    "@type" : "ImageObject",
    "url" : "https://www.bitovi.com/hubfs/Bitovi_July_2016_Theme/Images/canjs-background-blue.gif"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg"
    },
    "name" : "Bitovi"
  }
}
```