Skip to content

Functions and components to help MVVM-like development for React.

License

Notifications You must be signed in to change notification settings

jishida/react-mvvm

Repository files navigation

React MVVM

npm version CI Coverage Status license: Apache-2.0

Features

  • Wrapper functions and interfaces for React Hooks API to enable MVVM-like class design.
  • <Bind /> component to simplify re-rendering optimization.
  • API design to be as concise as possible with high affinity to typescript type checking and IntelliSense.

Installation

npm install @jishida/react-mvvm

or

yarn add @jishida/react-mvvm

Requirements

  • react >=16.8.0 || >=17.0.0 || >=18.0.0 or preact >=10.0.0
  • typescript >=4.1.0 if needed

Examples and Usage

Minimal Example

demo

javascript

typescript

import React from 'react';
import ReactDOM from 'react-dom';
import { Bind, observable } from '@jishida/react-mvvm';

const count = observable(0);

function increment() {
  count.value += 1;
}

ReactDOM.render(
  <Bind $type='button' onClick={increment}>
    increment: {count}
  </Bind>,
  document.getElementById('root')
);

The monitored variable manages its state through an Observable object created from the observable function. Bind component monitors Observable objects passed via props, resolves Observable objects to the component passed in $type prop, then passes the value. Bind component will be re-rendered when Observable objects passed via props is modified or whose notify method is called.

ViewModel Example

The minimal example is concise, but react-mvvm recommends that you classify states and actions as ViewModel.

demo

javascript

typescript

import React from 'react';
import ReactDOM from 'react-dom';
import { Bind, observable, proxy } from '@jishida/react-mvvm';

class IncrementViewModel {
  count = observable(0);

  // proxy function needs to be called after all Observable objects have been created.
  state = proxy<IncrementViewModel>(this, 'state');

  increment = () => {
    this.state.count += 1;
  }
}

const store = new IncrementViewModel();

ReactDOM.render(
  <Bind $type='button' onClick={store.increment}>
    increment: {store.count}
  </Bind>,
  document.getElementById('root')
);

Direct access to members of Observable objects such as value property is not intuitive and the code does not look good. Therefore, this library recommends using proxy function. proxy function provides six built-in proxies: 'ref', 'value', 'state', 'result', 'error' and 'message'. Those properties are type-safe and can be complemented by IntelliSense, making it more comfortable to code with typescript.

Re-render Optimization Example

Bind component will be re-rendered when there are changes to the Observable object received from props. It would be easier to understand this Stopwatch Example Demo if you enable the "Highlight updates when components render." option in React Developper Tools. Only components that need to be updated will be re-rendered.

demo

javascript

typescript

Material-UI Form Example

The Observable object can optionally have additional features.

demo

javascript

typescript

Using ref option, you can add RefObject for React to Observable object and save the code to access the DOM. You can also use validatable and parsable functions instead of observable function to create an object with Validatable interface that extends Observable interface. Validatable objects can be easily validated by specifying a validation or parsing function at initialization, and since they have properties of Observable type such as hasError and errorMessage, the results of validation can be bound to components. validator function creates a ViewModelValidator object, which can be used to manage all Validatable objects belonging to ViewModel by registering instances of ViewModel with it. By registering ViewModel instances with the ViewModelValidator object, ViewModel can manage all Validatable objects at once. In this example, by combining material-ui and these features, a form application is implemented with simple code.

Two different builds

There are two types of builds: full and lite. The lite version of the build does not include proxy, validatable, parsable, and resolveObject functions.

File Size

full:

lite:

ESModule

full:

import ReactMVVM from '@jishida/react-mvvm';

lite:

import ReactMVVM from '@jishida/react-mvvm/lite';

IIFE

full:

<script crossorigin src="https://unpkg.com/@jishida/react-mvvm@0.3/dist/react-mvvm.min.js"></script>

lite:

<script crossorigin src="https://unpkg.com/@jishida/react-mvvm@0.3/dist/react-mvvm-lite.min.js"></script>

Browser Support

React MVVM supports IE11, but Promise polyfill is required to use async options.

License

React MVVM is licensed under the Apache 2.0 License

About

Functions and components to help MVVM-like development for React.

Resources

License

Stars

Watchers

Forks

Packages

No packages published