README
Reactive Dictionaries
Observable dictionaries for React. For observable values for React, take a look at @yanfoo/react-var
.
Install
npm install @yanfoo/react-dict --save
yarn add @yanfoo/react-dict
Usage
import React, { useCallback } from 'react';
import { createReactDict, useReactDict } from '@yanfoo/react-dict';
// default comparator is equality : a === b
const foodPreferences = createReactDict(null, {
comparator: (a, b) => JSON.stringify(a) === JSON.stringify(b)
});
const FoodPreferenceFruit = () => {
const { apple:appleSelected, banana:bananaSelected, orange:orangeSelected } =
useReactDict(foodPreferences, [ 'apple', 'banana', 'orange' ]);
const handleClick = useCallback(e => foodPreferences({
[e.target.value]: selected => !selected
}), []);
return (
<div>
<div>
<input type="checkbox" id="checkFood1" value="apple" onClick={ handleClick } />
<label for="checkFood1"> I love apples</label>
</div>
<div>
<input type="checkbox" id="checkFood2" value="banana" onClick={ handleClick } />
<label for="checkFood2"> I love bananas</label>
</div>
<div>
<input type="checkbox" id="checkFood3" value="orange" onClick={ handleClick } />
<label for="checkFood3"> I love oranges</label>
</div>
</div>
);
};
const FoodPreferenceVegetable = () => {
const { carrot:carrotSelected, brocoli:brocoliSelected, celeri:celeriSelected } =
useReactDict(foodPreferences, [ 'carrot', 'brocoli', 'celeri' ]);
const handleClick = useCallback(e => foodPreferences({
[e.target.value]: selected => !selected
}, []);
return (
<div>
<div>
<input type="checkbox" id="checkFood1" value="carrot" onClick={ handleClick } />
<label for="checkFood1"> I love carrots</label>
</div>
<div>
<input type="checkbox" id="checkFood2" value="brocoli" onClick={ handleClick } />
<label for="checkFood2"> I love brocolis</label>
</div>
<div>
<input type="checkbox" id="checkFood3" value="celeri" onClick={ handleClick } />
<label for="checkFood3"> I love celeris</label>
</div>
</div>
);
};
API
declare type ReactDictChangeEvent<T> = {
/**
* The keys that have been updated
*/
updatedKeys: Array<string>,
/**
* The current handled values (including the keys that haven't updated)
*/
values(): Record<string,T>
}
export type ReactDict<T> = {
/**
* Set a new value and notify subscribers
*/
(newValue?: T | ((value: T) => T)): Promise<ReactDict<T>>;
/**
* Get a
*/
dictionary: Record<string,T>
/**
* Get the current values for the specified keys
*/
values(keys: Iterable<string>): Record<string,T>;
/**
* Register a new subscriber. Returns a function to unsubsribe the handler
* @param handler will be called with the updated value
*/
subscribe(handler: (event: ReactDictChangeEvent<T>) => Promise<void> | void): () => void;
/**
* Unregister a subscriber
* @param handler must be the exact same subscribed handler
*/
unsubscribe(handler: (event: ReactDictChangeEvent<T>) => Promise<void> | void): void;
};
export type ReactDictOptions<T> = {
comparator: (newVal: T, oldVal: T) => boolean,
transform: (newVal: T, oldVal: T, changed: boolean, key: string) => Promise<T> | T
};
export function createReactDict<T>(initialValue: T, options:ReactDictOptions<T>): ReactDict<T>;
/**
* Use the specified dictionary, subscribing to only the specified keys
* @param reactDict
* @param keys the list of keys to subscribe reactively
*/
export function useReactDict<T>(reactDict: ReactDict<T>, keys: Iterable<string>): Record<string,T>
Contribution
All contributions welcome! Every PR must be accompanied by their associated unit tests!
License
MIT