New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More โ†’
Socket
Sign inDemoInstall
Socket

statery

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

statery - npm Package Compare versions

Comparing version 0.6.3 to 0.7.0

dist/statery.cjs.d.ts.map

10

dist/declarations/src/index.d.ts

@@ -10,3 +10,3 @@ /**

*/
export declare type Store<T extends IState = Record<string, any>> = {
export type Store<T extends IState = Record<string, any>> = {
/**

@@ -45,7 +45,7 @@ * Return the current state.

};
export declare type StateUpdateFunction<T extends IState> = (state: Readonly<T>) => Partial<T>;
export type StateUpdateFunction<T extends IState> = (state: Readonly<T>) => Partial<T>;
/**
* Options for the `set` function.
*/
export declare type SetOptions = {
export type SetOptions = {
forceNotify?: boolean;

@@ -56,3 +56,3 @@ };

*/
export declare type Listener<T extends IState> = (updates: Readonly<Partial<T>>, state: Readonly<T>) => void;
export type Listener<T extends IState> = (updates: Readonly<Partial<T>>, state: Readonly<T>) => void;
/**

@@ -67,3 +67,3 @@ * Creates a Statery store and populates it with an initial state.

* provides direct access to the store's state and makes sure that the React component
* it was invoked from automaticaly re-renders when any of the data it uses is updated.
* it was invoked from automatically re-renders when any of the data it uses is updated.
*

@@ -70,0 +70,0 @@ * @param store The Statery store to access.

export * from "./declarations/src/index";
//# sourceMappingURL=statery.cjs.d.ts.map

@@ -7,41 +7,5 @@ 'use strict';

function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;

@@ -59,13 +23,4 @@ }

function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (!it) {

@@ -75,5 +30,3 @@ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {

var i = 0;
var F = function () {};
return {

@@ -96,9 +49,7 @@ s: F,

}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
didErr = false,
err;
return {

@@ -127,3 +78,20 @@ s: function () {

function _toPrimitive(input, hint) {
if (typeof input !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {

@@ -139,3 +107,2 @@ Object.defineProperty(obj, key, {

}
return obj;

@@ -146,3 +113,2 @@ }

var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {

@@ -154,6 +120,4 @@ var symbols = Object.getOwnPropertySymbols(object);

}
return keys;
}
function _objectSpread2(target) {

@@ -168,3 +132,2 @@ for (var i = 1; i < arguments.length; i++) {

}
return target;

@@ -176,3 +139,2 @@ }

var listeners = new Set();
var getActualChanges = function getActualChanges(updates) {

@@ -184,3 +146,2 @@ return Object.keys(updates).reduce(function (changes, prop) {

};
return {

@@ -190,22 +151,16 @@ get state() {

},
set: function set(incoming) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$forceNotify = _ref.forceNotify,
forceNotify = _ref$forceNotify === void 0 ? false : _ref$forceNotify;
_ref$forceNotify = _ref.forceNotify,
forceNotify = _ref$forceNotify === void 0 ? false : _ref$forceNotify;
var incomingState = incoming instanceof Function ? incoming(state) : incoming;
var updates = forceNotify ? incomingState : getActualChanges(incomingState);
if (Object.keys(updates).length > 0) {
var previousState = state;
state = _objectSpread2(_objectSpread2({}, state), updates);
var _iterator = _createForOfIteratorHelper(listeners),
_step;
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var _listener = _step.value;
_listener(updates, previousState);

@@ -219,3 +174,2 @@ }

}
return state;

@@ -231,50 +185,43 @@ },

};
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
var useStore = function useStore(store) {
var _useState = react.useState(0),
_useState2 = _slicedToArray(_useState, 2);
_useState2[0];
var setVersion = _useState2[1];
var subscribedProps = useConst(function () {
return new Set();
});
var initialState = useConst(function () {
return store.state;
});
useIsomorphicLayoutEffect(function () {
if (store.state === initialState) return;
subscribedProps.forEach(function (prop) {
if (initialState[prop] !== store.state[prop]) {
setVersion(function (v) {
return v + 1;
});
return;
}
});
}, [store]);
useIsomorphicLayoutEffect(function () {
var listener = function listener(updates) {
if (Object.keys(updates).find(function (prop) {
return subscribedProps.has(prop);
})) {
setVersion(function (v) {
return v + 1;
});
}
};
var prevSnapshot = react.useRef(store.state);
var subscribe = react.useCallback(function (listener) {
store.subscribe(listener);
return function () {
return void store.unsubscribe(listener);
return store.unsubscribe(listener);
};
}, [store]);
var getSnapshot = react.useCallback(function () {
var hasChanged = false;
var _iterator2 = _createForOfIteratorHelper(subscribedProps),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var prop = _step2.value;
if (store.state[prop] !== prevSnapshot.current[prop]) {
hasChanged = true;
break;
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
if (hasChanged) {
prevSnapshot.current = store.state;
}
return prevSnapshot.current;
}, [store]);
var snapshot = react.useSyncExternalStore(subscribe, getSnapshot);
return new Proxy({}, {
get: function get(_, prop) {
subscribedProps.add(prop);
return store.state[prop];
return snapshot[prop];
}
});
};
var useConst = function useConst(ctor) {

@@ -281,0 +228,0 @@ var ref = react.useRef(null);

@@ -7,41 +7,5 @@ 'use strict';

function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;

@@ -59,13 +23,4 @@ }

function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (!it) {

@@ -75,5 +30,3 @@ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {

var i = 0;
var F = function () {};
return {

@@ -96,9 +49,7 @@ s: F,

}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
didErr = false,
err;
return {

@@ -127,3 +78,20 @@ s: function () {

function _toPrimitive(input, hint) {
if (typeof input !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {

@@ -139,3 +107,2 @@ Object.defineProperty(obj, key, {

}
return obj;

@@ -146,3 +113,2 @@ }

var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {

@@ -154,6 +120,4 @@ var symbols = Object.getOwnPropertySymbols(object);

}
return keys;
}
function _objectSpread2(target) {

@@ -168,3 +132,2 @@ for (var i = 1; i < arguments.length; i++) {

}
return target;

@@ -176,3 +139,2 @@ }

var listeners = new Set();
var getActualChanges = function getActualChanges(updates) {

@@ -184,3 +146,2 @@ return Object.keys(updates).reduce(function (changes, prop) {

};
return {

@@ -190,22 +151,16 @@ get state() {

},
set: function set(incoming) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$forceNotify = _ref.forceNotify,
forceNotify = _ref$forceNotify === void 0 ? false : _ref$forceNotify;
_ref$forceNotify = _ref.forceNotify,
forceNotify = _ref$forceNotify === void 0 ? false : _ref$forceNotify;
var incomingState = incoming instanceof Function ? incoming(state) : incoming;
var updates = forceNotify ? incomingState : getActualChanges(incomingState);
if (Object.keys(updates).length > 0) {
var previousState = state;
state = _objectSpread2(_objectSpread2({}, state), updates);
var _iterator = _createForOfIteratorHelper(listeners),
_step;
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var _listener = _step.value;
_listener(updates, previousState);

@@ -219,3 +174,2 @@ }

}
return state;

@@ -231,50 +185,43 @@ },

};
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
var useStore = function useStore(store) {
var _useState = react.useState(0),
_useState2 = _slicedToArray(_useState, 2);
_useState2[0];
var setVersion = _useState2[1];
var subscribedProps = useConst(function () {
return new Set();
});
var initialState = useConst(function () {
return store.state;
});
useIsomorphicLayoutEffect(function () {
if (store.state === initialState) return;
subscribedProps.forEach(function (prop) {
if (initialState[prop] !== store.state[prop]) {
setVersion(function (v) {
return v + 1;
});
return;
}
});
}, [store]);
useIsomorphicLayoutEffect(function () {
var listener = function listener(updates) {
if (Object.keys(updates).find(function (prop) {
return subscribedProps.has(prop);
})) {
setVersion(function (v) {
return v + 1;
});
}
};
var prevSnapshot = react.useRef(store.state);
var subscribe = react.useCallback(function (listener) {
store.subscribe(listener);
return function () {
return void store.unsubscribe(listener);
return store.unsubscribe(listener);
};
}, [store]);
var getSnapshot = react.useCallback(function () {
var hasChanged = false;
var _iterator2 = _createForOfIteratorHelper(subscribedProps),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var prop = _step2.value;
if (store.state[prop] !== prevSnapshot.current[prop]) {
hasChanged = true;
break;
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
if (hasChanged) {
prevSnapshot.current = store.state;
}
return prevSnapshot.current;
}, [store]);
var snapshot = react.useSyncExternalStore(subscribe, getSnapshot);
return new Proxy({}, {
get: function get(_, prop) {
subscribedProps.add(prop);
return store.state[prop];
return snapshot[prop];
}
});
};
var useConst = function useConst(ctor) {

@@ -281,0 +228,0 @@ var ref = react.useRef(null);

@@ -1,42 +0,6 @@

import { useState, useRef, useLayoutEffect, useEffect } from 'react';
import { useRef, useCallback, useSyncExternalStore } from 'react';
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;

@@ -54,13 +18,4 @@ }

function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (!it) {

@@ -70,5 +25,3 @@ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {

var i = 0;
var F = function () {};
return {

@@ -91,9 +44,7 @@ s: F,

}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
didErr = false,
err;
return {

@@ -122,3 +73,20 @@ s: function () {

function _toPrimitive(input, hint) {
if (typeof input !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {

@@ -134,3 +102,2 @@ Object.defineProperty(obj, key, {

}
return obj;

@@ -141,3 +108,2 @@ }

var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {

@@ -149,6 +115,4 @@ var symbols = Object.getOwnPropertySymbols(object);

}
return keys;
}
function _objectSpread2(target) {

@@ -163,3 +127,2 @@ for (var i = 1; i < arguments.length; i++) {

}
return target;

@@ -171,3 +134,2 @@ }

var listeners = new Set();
var getActualChanges = function getActualChanges(updates) {

@@ -179,3 +141,2 @@ return Object.keys(updates).reduce(function (changes, prop) {

};
return {

@@ -185,22 +146,16 @@ get state() {

},
set: function set(incoming) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$forceNotify = _ref.forceNotify,
forceNotify = _ref$forceNotify === void 0 ? false : _ref$forceNotify;
_ref$forceNotify = _ref.forceNotify,
forceNotify = _ref$forceNotify === void 0 ? false : _ref$forceNotify;
var incomingState = incoming instanceof Function ? incoming(state) : incoming;
var updates = forceNotify ? incomingState : getActualChanges(incomingState);
if (Object.keys(updates).length > 0) {
var previousState = state;
state = _objectSpread2(_objectSpread2({}, state), updates);
var _iterator = _createForOfIteratorHelper(listeners),
_step;
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var _listener = _step.value;
_listener(updates, previousState);

@@ -214,3 +169,2 @@ }

}
return state;

@@ -226,50 +180,43 @@ },

};
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
var useStore = function useStore(store) {
var _useState = useState(0),
_useState2 = _slicedToArray(_useState, 2);
_useState2[0];
var setVersion = _useState2[1];
var subscribedProps = useConst(function () {
return new Set();
});
var initialState = useConst(function () {
return store.state;
});
useIsomorphicLayoutEffect(function () {
if (store.state === initialState) return;
subscribedProps.forEach(function (prop) {
if (initialState[prop] !== store.state[prop]) {
setVersion(function (v) {
return v + 1;
});
return;
}
});
}, [store]);
useIsomorphicLayoutEffect(function () {
var listener = function listener(updates) {
if (Object.keys(updates).find(function (prop) {
return subscribedProps.has(prop);
})) {
setVersion(function (v) {
return v + 1;
});
}
};
var prevSnapshot = useRef(store.state);
var subscribe = useCallback(function (listener) {
store.subscribe(listener);
return function () {
return void store.unsubscribe(listener);
return store.unsubscribe(listener);
};
}, [store]);
var getSnapshot = useCallback(function () {
var hasChanged = false;
var _iterator2 = _createForOfIteratorHelper(subscribedProps),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var prop = _step2.value;
if (store.state[prop] !== prevSnapshot.current[prop]) {
hasChanged = true;
break;
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
if (hasChanged) {
prevSnapshot.current = store.state;
}
return prevSnapshot.current;
}, [store]);
var snapshot = useSyncExternalStore(subscribe, getSnapshot);
return new Proxy({}, {
get: function get(_, prop) {
subscribedProps.add(prop);
return store.state[prop];
return snapshot[prop];
}
});
};
var useConst = function useConst(ctor) {

@@ -276,0 +223,0 @@ var ref = useRef(null);

@@ -1,2 +0,2 @@

Copyright (c) 2020 Hendrik Mans
Copyright (c) 2023 Hendrik Mans

@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining

@@ -6,3 +6,3 @@ {

"email": "hendrik@mans.de",
"url": "https://hendrik.mans.de"
"url": "https://hmans.dev"
},

@@ -18,6 +18,6 @@ "description": "A happy little state management library for React and friends.",

"sideEffects": false,
"version": "0.6.3",
"version": "0.7.0",
"main": "dist/statery.cjs.js",
"module": "dist/statery.esm.js",
"types": "dist/statery.cjs.js",
"types": "dist/statery.cjs.d.ts",
"files": [

@@ -34,31 +34,24 @@ "dist/",

"@babel/preset-react",
[
"@babel/preset-typescript",
{
"isTSX": true,
"allExtensions": true
}
]
"@babel/preset-typescript"
]
},
"devDependencies": {
"@babel/core": "^7.19.0",
"@babel/preset-env": "^7.19.0",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@changesets/cli": "^2.24.1",
"@preconstruct/cli": "^2.2.1",
"@testing-library/react": "^13.3.0",
"@types/jest": "^28.1.6",
"@types/react": "^18.0.19",
"@types/react-dom": "^18.0.0",
"jest": "^28.1.3",
"jest-environment-jsdom": "^28.1.3",
"@babel/core": "^7.22.9",
"@babel/preset-env": "^7.22.9",
"@babel/preset-react": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@changesets/cli": "^2.26.2",
"@preconstruct/cli": "^2.8.1",
"@testing-library/react": "^14.0.0",
"@types/jest": "^29.5.3",
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"jest": "^29.6.2",
"jest-environment-jsdom": "^29.6.2",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"rimraf": "^3.0.2",
"ts-jest": "^28.0.7",
"tslib": "^2.0.3",
"typedoc": "^0.23.9",
"typescript": "^4.1.3"
"rimraf": "^5.0.1",
"ts-jest": "^29.1.1",
"tslib": "^2.6.1",
"typescript": "^5.1.6"
},

@@ -68,2 +61,7 @@ "peerDependencies": {

},
"peerDependenciesMeta": {
"react": {
"optional": true
}
},
"scripts": {

@@ -74,7 +72,6 @@ "clean": "rimraf dist",

"test": "jest",
"docs": "typedoc src/index.ts",
"ci": "preconstruct validate && pnpm build && pnpm test",
"ci:test": "preconstruct validate && pnpm build && pnpm test",
"ci:version": "changeset version && pnpm install --no-frozen-lockfile",
"ci:release": "pnpm ci && pnpm changeset publish"
"ci:release": "pnpm ci:test && pnpm changeset publish"
}
}

@@ -16,3 +16,3 @@ ```

[![Version](https://img.shields.io/npm/v/statery?style=for-the-badge)](https://www.npmjs.com/package/statery)
[![CI](https://img.shields.io/github/workflow/status/hmans/statery/CI?style=for-the-badge)](https://github.com/hmans/statery/actions?query=workflow%3ACI)
![CI](https://img.shields.io/github/actions/workflow/status/hmans/statery/tests.yml?style=for-the-badge)
[![Downloads](https://img.shields.io/npm/dt/statery.svg?style=for-the-badge)](https://www.npmjs.com/package/statery)

@@ -26,3 +26,3 @@ [![Bundle Size](https://img.shields.io/bundlephobia/min/statery?label=bundle%20size&style=for-the-badge)](https://bundlephobia.com/result?p=statery)

- Fully **tested**, fully **typed**!
- **Designed for React** (with functional components and hooks), but can also be used **without it**.
- **Designed for React** (with functional components and hooks), but can also be used **without it**, or with other frameworks (but you may need to bring your own glue.)

@@ -37,18 +37,6 @@ ### Non-Features ๐Ÿงค

### Comparison to Zustand
[Zustand](https://github.com/pmndrs/zustand) is a lovely minimal state management library for React, and Statery may feel very similar to it. Here are the key differences:
- In Zustand, **data and the functions that modify it are all stored in the same object**. I believe this to be architecturally unwise (the README even warns the user not to accidentally overwrite their store's API.) Furthermore, this leads to Zustand [not being able to infer the type](https://github.com/pmndrs/zustand/blob/main/docs/guides/typescript.md) of the state data from the `create` function's first argument, forcing you to provide it explicitly (including the API, because it's part of the state... and so on.)
Statery doesn't share these problems; **stores _only_ contain data**. The store's type is inferred from the initial state passed into `makeStore`. You can either modify the state directly through `set`, or โ€“ the recommended approach โ€“ export an API for your store as a set of functions (see the examples in this document or the [demo] for what this looks like.)
- When accessing data using Zustand's `useStore` hook, **it expects you to provide a selector function** that returns the data you want. Statery's `useStore` instead uses a **transparent proxy** that automatically registers all state properties you acceess. **You don't have to do anything special** to use this, and you never have to worry about causing re-renders for updated data your component isn't actually interested in.
- Not that it matters much with packages this tiny, but Statery is _even smaller_ than Zustand (at roughly 50% the size.)
## SUMMARY
```tsx
import { value makeStore, value useStore } from "statery"
import { makeStore, useStore } from "statery"

@@ -74,2 +62,4 @@ const store = makeStore({ counter: 0 })

For a more fully-featured example, please check out the [demo].
## BASIC USAGE

@@ -104,5 +94,11 @@

If you're using TypeScript, the type of the store state will be inferred from the initial state; but you may also pass a type argument to `makeStore` to explicitly set the type of the store:
```ts
const store = makeStore<{ count: number }>({ count: 0 })
```
### Updating the Store
Update the store contents using its `set` function:
The store object's `set` function will update the store's state and notify any listeners who have subscribed to changes:

@@ -147,3 +143,3 @@ ```tsx

When any of the data your components access changes in the store, they will automatically re-render.
When any of the store's properties that your component accesses are updated, they will automatically re-render, automatically receiving the new state.

@@ -194,10 +190,10 @@ ### Reading from a Store (without React)

...as well as React components, which will automatically be rerendered if any of the underlying data changes:
...as well as React components, which will automatically be re-rendered if any of the underlying data changes:
```tsx
const BuyHouseButton = () => {
const proxy = useStore(store)
const store = useStore(store)
return (
<button onClick={buyHouse} disabled={!canBuyHouse(proxy)}>
<button onClick={buyHouse} disabled={!canBuyHouse(store)}>
Buy House (5g, 5w)

@@ -248,25 +244,2 @@ </button>

### Async updates
Your Statery store doesn't know or care about asynchronicity -- simply call `set` whenever your data is ready:
```ts
const fetchPosts = async () => {
const posts = await loadPosts()
store.set({ posts })
}
```
### TypeScript support
Statery is written in TypeScript, and its stores are fully typed. `useStore` knows about the structure of your store, and if you're about to update a store with a property that it doesn't know about, TypeScript will warn you.
If the state structure `makeStore` infers from its initial state argument is not what you want, you can explicitly pass a store type to `makeStore`:
```tsx
const store = makeStore<{ name?: string }>({})
store.set({ name: "Statery" })
store.set({ foo: 123 })
```
## NOTES

@@ -282,3 +255,3 @@

Statery is written and maintained by Hendrik Mans. [Get in touch on Twitter](https://twitter.com/hmans)!
Statery is written and maintained by [Hendrik Mans](https://www.hmans.dev/).

@@ -285,0 +258,0 @@ [demo]: https://codesandbox.io/s/statery-clicker-game-hjxk3?file=/src/App.tsx

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc