All Projects → sindresorhus → On Change

sindresorhus / On Change

Licence: mit
Watch an object or array for changes

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Projects that are alternatives of or similar to On Change

Cpx
A cli tool to watch and copy file globs.
Stars: ✭ 394 (-76.95%)
Mutual labels:  watch, npm-package
Typy
Minimal JavaScript type checking library
Stars: ✭ 215 (-87.42%)
Mutual labels:  object, npm-package
Fnv1a
FNV-1a non-cryptographic hash function
Stars: ✭ 101 (-94.09%)
Mutual labels:  npm-package
Teenyicons
Tiny minimal 1px icons designed to fit in the smallest places.
Stars: ✭ 1,631 (-4.56%)
Mutual labels:  npm-package
Youtube Local
browser-based client for watching Youtube anonymously and with greater page performance
Stars: ✭ 112 (-93.45%)
Mutual labels:  watch
Cliflix
Watch anything instantaneously, just write its name.
Stars: ✭ 1,439 (-15.8%)
Mutual labels:  watch
Is Plain Object
Returns true if the given value is an object created by the Object constructor.
Stars: ✭ 112 (-93.45%)
Mutual labels:  object
Pageres Cli
Capture website screenshots
Stars: ✭ 1,378 (-19.37%)
Mutual labels:  npm-package
Php Server
Start a PHP server
Stars: ✭ 119 (-93.04%)
Mutual labels:  npm-package
P Queue
Promise queue with concurrency control
Stars: ✭ 1,863 (+9.01%)
Mutual labels:  npm-package
Wordup Cli
Wordup is a fully integrated development platform for WordPress. Develop plugins and themes locally. Preview in the cloud. Automatic updates in WP.
Stars: ✭ 116 (-93.21%)
Mutual labels:  npm-package
Cra Build Watch
A script for create-react-app that writes development builds to the disk
Stars: ✭ 110 (-93.56%)
Mutual labels:  watch
Jus
🍉 An opinionated tool for making static websites with browserify
Stars: ✭ 107 (-93.74%)
Mutual labels:  watch
Node Rus Diff
JSON diff
Stars: ✭ 112 (-93.45%)
Mutual labels:  npm-package
Npm Package Json Lint
Configurable linter for package.json files
Stars: ✭ 106 (-93.8%)
Mutual labels:  npm-package
Doge Seed Cli
Generate dank mnemonic seed phrases in the terminal
Stars: ✭ 118 (-93.1%)
Mutual labels:  npm-package
New Github Release Url
Generate a URL for opening a new GitHub release with prefilled tag, body, and other fields
Stars: ✭ 102 (-94.03%)
Mutual labels:  npm-package
Chalk Animation
🎬 Colorful animations in terminal output
Stars: ✭ 1,489 (-12.87%)
Mutual labels:  npm-package
Hermes
Client-side messaging channel for sending data from one browser tab to another
Stars: ✭ 111 (-93.5%)
Mutual labels:  npm-package
Update Notifier
The idea for this module came from the desire to apply the browser update strategy to CLI tools, where everyone is always on the latest version. We first tried automatic updating, which we discovered wasn't popular. This is the second iteration of that idea, but limited to just update notifications.
Stars: ✭ 1,594 (-6.73%)
Mutual labels:  npm-package

on-change

Watch an object or array for changes

It works recursively, so it will even detect if you modify a deep property like obj.a.b[0].c = true.

Uses the Proxy API.

Install

$ npm install on-change

Usage

import onChange from 'on-change';

const object = {
	foo: false,
	a: {
		b: [
			{
				c: false
			}
		]
	}
};

let index = 0;
const watchedObject = onChange(object, function (path, value, previousValue, applyData) {
	console.log('Object changed:', ++index);
	console.log('this:', this);
	console.log('path:', path);
	console.log('value:', value);
	console.log('previousValue:', previousValue);
	console.log('applyData:', applyData);
});

watchedObject.foo = true;
//=> 'Object changed: 1'
//=> 'this: {
//   	foo: true,
//   	a: {
//   		b: [
//   			{
//   				c: false
//   			}
//   		]
//   	}
//   }'
//=> 'path: "foo"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'applyData: undefined'

watchedObject.a.b[0].c = true;
//=> 'Object changed: 2'
//=> 'this: {
//   	foo: true,
//   	a: {
//   		b: [
//   			{
//   				c: true
//   			}
//   		]
//   	}
//   }'
//=> 'path: "a.b.0.c"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'applyData: undefined'

watchedObject.a.b.push(3);
//=> 'Object changed: 3'
//=> 'this: {
//   	foo: true,
//   	a: {
//   		b: [
//   			{
//   				c: true
//   			},
//   			3
//   		]
//   	}
//   }'
//=> 'path: "a.b"'
//=> 'value: [{c: true}, 3]'
//=> 'previousValue: [{c: true}]'
//=> 'applyData: {
//       name: "push",
//       args: [3],
//       result: 2,
//   }'

// Access the original object
onChange.target(watchedObject).foo = false;
// Callback isn't called

// Unsubscribe
onChange.unsubscribe(watchedObject);
watchedObject.foo = 'bar';
// Callback isn't called

API

onChange(object, onChange, options?)

Returns a version of object that is watched. It's the exact same object, just with some Proxy traps.

object

Type: object

Object to watch for changes.

onChange

Type: Function

Function that gets called anytime the object changes.

The function receives four arguments:

  1. A path to the value that was changed. A change to c in the above example would return a.b.0.c.
  2. The new value at the path.
  3. The previous value at the path. Changes in WeakSets and WeakMaps will return undefined.
  4. An object with the name of the method that produced the change, the args passed to the method, and the result of the method.

The context (this) is set to the original object passed to onChange (with Proxy).

options

Type: object

Options for altering the behavior of onChange.

isShallow

Type: boolean
Default: false

Deep changes will not trigger the callback. Only changes to the immediate properties of the original object.

equals

Type: Function
Default: Object.is

The function receives two arguments to be compared for equality. Should return true if the two values are determined to be equal. Useful if you only need a more loose form of equality.

ignoreSymbols

Type: boolean
Default: false

Setting properties as Symbol won't trigger the callback.

ignoreKeys

Type: Array<string | symbol>
Default: undefined

Setting properties in this array won't trigger the callback.

ignoreUnderscores

Type: boolean
Default: false

Setting properties with an underscore as the first character won't trigger the callback.

pathAsArray

Type: boolean
Default: false

The path will be provided as an array of keys instead of a delimited string. Recommended when working with Sets, Maps, or property keys that are Symbols.

ignoreDetached

Type: boolean
Default: false

Ignore changes to objects that become detached from the watched object.

details

Type: boolean|string[]
Default: false

Trigger callbacks for each change within specified method calls or all method calls.

onValidate

Type: Function

The function receives the same arguments and context as the onChange callback. The function is called whenever a change is attempted. Returning true will allow the change to be made and the onChange callback to execute, returning anything else will prevent the change from being made and the onChange callback will not trigger.


onChange.target(object)

Returns the original unwatched object.

object

Type: object

Object that is already being watched for changes.

onChange.unsubscribe(object)

Cancels all future callbacks on a watched object and returns the original unwatched object.

object

Type: object

Object that is already being watched for changes.

Use-case

I had some code that was like:

const foo = {
	a: 0,
	b: 0
};

// …

foo.a = 3;
save(foo);

// …

foo.b = 7;
save(foo);


// …

foo.a = 10;
save(foo);

Now it can be simplified to:

const foo = onChange({
	a: 0,
	b: 0
}, () => save(foo));

// …

foo.a = 3;

// …

foo.b = 7;

// …

foo.a = 10;

Related

  • known - Allow only access to known object properties (Uses Proxy too)
  • negative-array - Negative array index support array[-1] (Uses Proxy too)
  • atama - State manager (Uses Proxy too)
  • introspected - Never-ending Proxy with multiple observers (Uses Proxy too)

Maintainers

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].