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, includingcomponentDidMount
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
- Allows ViewModel-first with
ViewModel.connect
, a higher-order-component that
props.vm
.- Event-forwarding for view-aware ViewModels with
ViewComponent.forwardEvents
ViewComponent
) and the ViewAware
base-ViewModel class.- Automatically binds
ViewModel
function properties. (See ViewModel-first
- Coming soon: Redux integration. Put all of your Redux state mapping in your
connect
.ViewModel-first Example
See theexample/
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
);