react-mvvm

A MVVM pattern for React

Stats

StarsIssuesVersionUpdatedCreatedSize
react-mvvm
1.0.03 years ago5 years agoMinified + gzip package size for react-mvvm in KB

Readme

react-mvvm

A MVVM pattern for React.

npmjs.com

What is it?

React-MVVM is an implementation of the Model-View-ViewModel pattern for React. It allows you to move virtually all "code-behind" logic from your JSX component modules, including componentDidMount and other view functions, into a ViewModel object. This ViewModel object is then passed as a prop to your JSX.

You can read more about MVVM on Wikipedia.

Install

npm install react-mvvm    or    yarn add react-mvvm

Features

  • Allows View-first style MVVM, where the View creates its own ViewModel or is passed one by a parent component.
  • Allows ViewModel-first with ViewModel.connect, a higher-order-component that instantiates the ViewModel and passes it to your component as props.vm.
  • Event-forwarding for view-aware ViewModels with ViewComponent.forwardEvents (or inheriting ViewComponent) and the ViewAware base-ViewModel class.
  • Automatically binds ViewModel function properties. (See ViewModel-first example below.)
  • Coming soon: Redux integration. Put all of your Redux state mapping in your ViewModel without calling Redux connect.

ViewModel-first Example

See the example/ directory for a full example. Summarized below.

The example below only shows one way of exposing a ViewModel to your View.

Define a view that forwards events to a ViewModel and uses the commands provided by the ViewModel.

// file: ./Dashboard.jsx
import React from 'react';
import MVVM from 'react-mvvm';

export default class Dashboard extends MVVM.ViewComponent {
  render() {
    return (
      <div>
        <h1>Dashboard</h1>
        <p>
          Welcome.
        </p>
        <button onClick={this.props.sayHello}>
          Say Hello
        </button>
        <button onClick={this.props.sayGoodbye}>
          Say Goodbye
        </button>
        <button onClick={this.props.vm.doSomethingElse()}>
          Do Something Else
        </button>
      </div>
    );
  }
  /*
  constructor(props) {
    super(props);
    // You can also just forward events instead of inheriting ViewComponent.
    ViewComponent.forwardEvents(this, props.vm);
  } // */
}

Define the ViewModel.

// file: ./Dashboard.vm.js
import { 
  ViewModel,
  ViewAware,
} from 'react-mvvm';
import Dashboard from './Dashboard';

class DashboardVM extends ViewAware {

  // Functional class properties, automatically passed as view props.

  sayHello = () => {
    alert('Hello, my little friend.');
  };

  sayGoodbye = () => {
    alert('Goodbye!');
  };

  // Prototype methods are NOT passed as view props.

  componentDidMount() {
    console.log('DashboardVM.componentDidMount');
  }
  
  componentDidUpdate(prevProps, prevState, prevContext) {
    console.log('DashboardVM.componentDidUpdate');
  }

  componentWillUnmount() {
    console.log('DashboardVM.componentWillUnmount');
  }

  // However, if you wish to call a prototype method from the view,
  // the entire DashboardVM class instance is passed to the view as
  // `props.vm`.

  doSomethingElse() {
    return () => {
      alert('Doing something else...');
    };
  }

}

export default ViewModel.connect(
  DashboardVM, 
  Dashboard
);

API

See: docs/API.md

If you find any bugs or have a feature request, please open an issue on github!

The npm package download data comes from npm's download counts api and package details come from npms.io.