0.3.2 • Published 3 months ago
reactivity-store v0.3.2
RStore
A React state-management, inspired by the Vue
and zustand
a React state-management power by Reactive api, which mean you can use Vue Reactive api in React app, any change of the state will make then UI auto update!
Install
# use pnpm
pnpm add reactivity-store
# or use npm/yarn
Example
import { createStore, ref } from "reactivity-store";
// simple reactive store
const useCount = createStore(() => {
const refValue = ref(0);
// this is the only valid way to define the change state function (in the `createStore` function)
const changeRef = (v) => (refValue.value = v);
return { refValue, changeRef };
});
const App = () => {
const { ref, change } = useCount((state) => ({
// the state is a readonly value, so we can't change state here
// the `ref` value which return from `createStore` will be auto unwrap
ref: state.refValue,
change: state.changeRef,
}));
return (
<div>
<p>{ref}</p>
<button onClick={() => change(ref + 1)}>add</button>
</div>
);
};
createState
support middleware
import { createState, withPersist, withActions } from "reactivity-store";
// simple reactive state, but we can't change the state
const useCount = createState(() => {
return { count: 0 };
});
// simple reactive state with middleware
// the `withPersist` middleware support auto cache the `state` to the `Storage` when the `state` change
const useCount = createState(withPersist(() => ({ count: 0 }), { key: "count" }));
// the `withActions` middleware support define the action for the state
const useCount = createState(withActions(() => ({ count: 0 }), { generateActions: (state) => ({ add: () => state.count++ }) }));
// then you can get the action from the `selector`
const { count, add } = useCount((state) => ({ count: state.count, add: state.add }));
// you can also compose this two middleware
// or you can use the `option` api with full type support, it is very simple to use
const useCount = createState(() => ({ count: 0 }), { withActions: (state) => ({ add: () => state.count++ }), withPersist: "count" });
// the createState have the same usage with createStore
const App = () => {
const { count, add } = useCount();
return (
<div>
<p>{count}</p>
<button onClick={add}>add</button>
</div>
);
};
createStoreWithComponent
support lifeCycle
import { createStoreWithComponent, onMounted, onUpdated, ref } from "reactivity-store";
// reactive store with component lifeCycle
const Count = createStoreWithComponent({
setup: () => {
const refValue = ref(0);
const changeRef = (v) => (refValue.value = v);
onUpdated(() => {
console.log("component updated");
});
onMounted(() => {
console.log("component mounted");
});
return { refValue, changeRef };
},
});
const App = () => {
return (
<div>
<Count>
{({ refValue, changeRef }) => (
<>
<p>{refValue}</p>
<button onClick={() => changeRef(refValue + 1)}>add</button>
</>
)}
</Count>
</div>
);
};
v0.1.9 update
Pure hook api for reactive
state;
import { useReactiveEffect, useReactiveState } from "reactivity-store";
const usePosition = () => {
// the `state` object will be a reactive object;
// so every change for this object will cause the component auto update
// also support a function as the params
const [state, setState] = useReactiveState({ x: 0, y: 0 });
// the second value is a `setState` function, this function expect receive a callback function which has the reactiveState as params
// so we can update the state in the callback function
const [xPosition, setXPosition] = useReactiveState({ x: 0 });
useReactiveEffect(() => {
const listener = (e: MouseEvent) => {
setState((state) => {
state.x = e.clientX;
state.y = e.clientY;
});
};
window.addEventListener("mousemove", listener);
// same behavior as `useEffect`
return () => window.removeEventListener("mousemove", listener);
});
// when the component mount or the `state.x` has changed, the effect callback will be invoked
// because of the `xPosition` is a `state` which create by `useReactiveState`, so the change will cause component auto update
// no need deps for reactive hook
useReactiveEffect(() => {
// update the state
// callback / object
setXPosition({
x = state.x;
});
});
return { y: state.y, x: xPosition.x };
};
Subscribe a state change
import { createState } from "reactivity-store";
const useCount = createState(() => ({ count: 0 }), { withActions: (s) => ({ add: () => s.count++ }) });
// you can use subscribe anywhere
const unSubscribe = useCount.subscribe((s) => s.count, callback);
v0.2.4 update
createState
support withDeepSelector
option
import { createState, withActions, withPersist } from "reactivity-store";
const useCount = createState(
withActions(
() => {
const data = { re: { count: 0 } };
return data;
},
{ generateActions: (state) => ({ add: () => state.re.count++, del: () => state.re.count-- }) }
),
{
// make the selector support deep selector
/**
* state is `{a: {b: '1'}}`
* select is `const re = (state) => state.a;`
* if `withDeepSelector` is true, when the `re.b` state change, the selector will also be trigger
* if `withDeepSelector` is false, when the `re.b` state change, the selector will not be trigger
*
* the default value for the `withDeepSelector` is true
*/
withDeepSelector: true;
}
);
const App = () => {
// the `withDeepSelector` option is true, the selector will be trigger when the `re.count` state change, so the component will update normally
const { re, add } = useCount((state) => ({ re: state.re, add: state.add }));
return (
<div>
<p>React Reactive Count</p>
<p>{re.count}</p>
<button onClick={add}>Add</button>
</div>
);
};
const useCount_2 = createState(
withActions(
() => {
const data = { re: { count: 0 } };
return data;
},
{ generateActions: (state) => ({ add: () => state.re.count++, del: () => state.re.count-- }) }
),
{
withDeepSelector: false;
}
);
const App = () => {
//the `withDeepSelector` option is false, the selector will not be trigger when the `re.count` state change, so the component will not update
const { re, add } = useCount_2((state) => ({ re: state.re, add: state.add }));
return (
<div>
<p>React Reactive Count</p>
<p>{re.count}</p>
<button onClick={add}>Add</button>
</div>
);
};
v0.2.6 update
createState
support withNameSpace
option for reduxDevTools
in develop mode
import { createState, withActions, withNameSpace } from "reactivity-store";
const useCount = createState(
withActions(
withNameSpace(
() => {
const data = { re: { count: 0 } };
return data;
},
{
namespace: "useCount",
reduxDevTool: true,
}
),
{ generateActions: (state) => ({ add: () => state.re.count++, del: () => state.re.count-- }) }
)
);
or
import { createState } from "reactivity-store";
const useCount = createState(
() => {
const data = { re: { count: 0 } };
return data;
},
{
withNamespace: "useCount",
withActions: (state) => ({ add: () => state.re.count++, del: () => state.re.count-- }),
}
);
License
MIT
0.3.2
3 months ago
0.3.1
4 months ago
0.3.0
5 months ago
0.2.7
6 months ago
0.2.6
6 months ago
0.2.9
5 months ago
0.2.8
6 months ago
0.2.5
7 months ago
0.2.4
7 months ago
0.2.3
8 months ago
0.2.2
8 months ago
0.2.1
8 months ago
0.2.0
9 months ago
0.1.9
9 months ago
0.1.8
10 months ago
0.1.7
10 months ago
0.1.6
10 months ago
0.1.5
10 months ago
0.1.4
10 months ago
0.1.3
10 months ago
0.1.2
10 months ago
0.1.1
10 months ago
0.1.0
10 months ago
0.0.9
11 months ago
0.0.8
11 months ago
0.0.7
11 months ago
0.0.6
11 months ago
0.0.5
11 months ago
0.0.4
11 months ago
0.0.3
11 months ago
0.0.2
11 months ago
0.0.1
11 months ago