@jishida/react-mvvm
v0.4.0
Published
Functions and components to help MVVM-like development for React.
Downloads
2
Maintainers
Readme
React MVVM
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
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.
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 the Observable bject has 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.
Material-UI Form Example
The Observable object can optionally have additional features.
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.