@archer-oss/dependency-checker-react
v1.3.3
Published
A React Context Provider for state management that's powered by a dependency checker
Downloads
2
Readme
dependency-checker-react
A React Context Provider for state management that's powered by a dependency checker. The context provider takes data
, metaData
and dependencies
to allow for state and state relationships to be modeled declaratively.
Props
onChange (optional)
onChange: (
data: DataCollection,
metaData: MetaDataCollection,
details: { type: 'key-update'; key: string } | { type: 'dependency-calculation'; keys: string[] },
) => void;
An event handler which is triggered anytime the internal data is updated, either by explicit data updates or through data updates which are triggered through dependency calculations.
onGetSnapshot (optional)
onGetSnapshot: (data: DataCollection, metaData: MetaDataCollection) => void;
An event handler which can be manually triggered at anytime by using the generateSnapshot
action handler with the Dependency Checker dispatcher.
import { generateSnapshot, useDependencyCheckerDispatch } from 'dependency-checker-react';
// Rendered inside the provider
function MyComponent() {
const dispatch = useDependencyCheckerDispatch();
// Clicking this will fire the `onGetSnapshot` callback
// which was passed to the wrapping provider component.
return <button onClick={() => generateSnapshot(dispatch)}>Click Me</button>;
}
data
A collection of key value pairs where the key is the unique identifier for subscriptions and dependencies. The value is an object containing any properties.
type Data = Record<string, any>;
type DataCollection = Record<string, Data>;
const data: DataCollection = {
'key-one': { someProperty: 'some value' },
'key-two': { someOtherProperty: 'some other value' },
};
metaData
A collection of key value pairs where the key is the unique identifier for subscriptions and dependencies. The value is an object containing any properties.
type MetaData = Record<string, any>;
type MetaDataCollection = Record<string, MetaData>;
const metaData: MetaDataCollection = {
'key-one': { someProperty: 'some value' },
'key-two': { someOtherProperty: 'some other value' },
};
dependencies (optional)
A collection of key value pairs where the key is the unique identifier. The value is an array of dependency objects which are used for internal calculations. Each array of dependency objects are assigned to the unique identifier.
type Dependency = {
// The key which its dependent on.
key: 'unique-identifier',
type: 'type used for typescript support',
// A condition which gets the data and metaData
// for the unique identifier (`key`) above and
// returns a boolean. If the condition is `true`
// apply the effects on top of the data.
cond: (data: Data, metaData: MetaData) => boolean,
effects: Data | ((data: Data, metaData: MetaData) => Data)
};
type DependencyCollection: Record<string, Dependency[]>;
const dependencies: DependencyCollection = {
'key-one': [
{
// `key-one` is dependent on `key-two`
// (i.e. if `key-two` state changes then rerun this dependency for `key-one`)
key: 'key-two',
type: 'used for typescript support',
// data and metaData are for `key-two`
cond: (data, metaData) => data.someProperty === 'some value' || metaData.someOtherProperty === 'some other value',
// If the cond above is `true` then stack
// the effects object on top of the data for `key-one`.
// Effects always stack, which means an effect which targets
// the same property as another effect but comes later
// in the list will take priority. The underlying data
// is not affected. If the dependency is rerun at a later
// point and the cond is `false` then the effects are just
// removed from the stack and the underlying data is used.
// NOTE: `effects` can also just be an object (i.e. { someProperty: 'some other value' })
effects: (data, metaData) => {
return { someProperty: metaData.someOtherProperty };
}
}
]
};
dependencyCheckerRate (optional)
A number that determines how long the dependency checker should wait between state updates to recalculate dependencies. Internally the dependency checker operation is debounced. If no dependency checker rate is provided or the rate is set to 0
then the calculation will be synchronous (i.e. it will run after every state update).
resetConfig (optional)
type ResetStateUpdater<State> = State | ((nextState: State, prevState: State) => State);
type ResetConfig = {
resetKeys?: {
data?: any[];
metaData?: any[];
};
resetStateRef?: React.MutableRefObject<
| {
resetData: (updater?: ResetStateUpdater<DataCollection>) => void;
resetMetaData: (updater?: ResetStateUpdater<MetaDataCollection>) => void;
}
| undefined
>;
};
An object containing a resetKeys
and a resetStateRef
property. Both properties can be used to control when the dependency checker resets its internal state.
resetKeys
An object containing a data
and metaData
property which are both arrays containing any values. If the values in the array change between renders then that property will be updated internally. This behavior is similar to how a React.useEffect
dependency array works.
- If the
data
property isundefined
that means that the data will be reset on every render. - If the
data
property is an empty array that means that the data will never be reset between renders. - If the data property is an array with the variable
someVariable
in it (i.e.{ data: [someVariable] }
) then the data will be reset only ifsomeVariable
changes between renders.
Note: This behavior is consistent for the metaData
property as well.
resetStateRef
A standard React.useRef
value which is modified using React.useImperativeHandle
to provide utility functions which can be used to reset the data or metaData at any point. If the utility functions are invoked without any arguments then the state will be reset using the latest props that were passed into the provider.
function MyComponent() {
const resetStateRef = React.useRef();
// Other props left out for the sake of brevity
const dependencyCheckerProps = { ... };
return (
<React.Fragment>
<DependencyCheckerProvider {...dependencyCheckerProps} resetConfig={{ resetStateRef }} />
<button
onClick={() => {
resetStateRef.current?.resetData({ newDataProperty: 'new value' });
resetStateRef.current?.resetMetaData({ newMetaDataProperty: 'new value' });
// Updater functions can be used as well.
// The next value is the latest data or metaData
// for a key which have been passed in as props.
// The prev value is the current data or metaData
// for a key which is stored in the provider's state.
resetStateRef.current?.resetData((nextData, prevData) => ({ ...prevData, newDataProperty: 'new value' }));
resetStateRef.current?.resetMetaData((nextMetaData, prevMetaData) => nextMetaData);
}}
>
Click Me
</button>
</React.Fragment>
);
}