diff --git a/README.md b/README.md
index 35b9748..2487b97 100644
--- a/README.md
+++ b/README.md
@@ -123,6 +123,24 @@ Rex added a log even in release mode for debugging, add run this to turn on:
window.REX_DEV_LOG = true;
```
+### `useAtom`
+
+```tsx
+// "Clojure Atom"-like state management
+let dataAtom = useAtom({ a: 1 });
+
+let onClick = () => {
+ // get latest state
+ dataAtom.deref();
+ // replace data
+ dataAtom.resetWith({ a: 0 });
+ // update data by function, frozen by immer
+ dataAtom.swapWith((data) => {
+ data.a += 1;
+ });
+};
+```
+
### Workflow
https://github.com/jimengio/ts-workflow
diff --git a/example/demo-atom.tsx b/example/demo-atom.tsx
new file mode 100644
index 0000000..60a374b
--- /dev/null
+++ b/example/demo-atom.tsx
@@ -0,0 +1,39 @@
+import React, { FC } from "react";
+import { css } from "emotion";
+import { useAtom } from "../src/use-atom";
+
+let DemoAtom: FC<{ className?: string }> = React.memo((props) => {
+ let dataAtom = useAtom({ a: 1 });
+
+ /** Plugins */
+ /** Methods */
+ /** Effects */
+ /** Renderers */
+ return (
+
+
{JSON.stringify(dataAtom.deref(), null, 2)}
+
+
+
+
+
+
+
+ );
+});
+
+export default DemoAtom;
diff --git a/example/pages/container.tsx b/example/pages/container.tsx
index 0263706..0fa4ce6 100644
--- a/example/pages/container.tsx
+++ b/example/pages/container.tsx
@@ -5,6 +5,7 @@ import randomcolor from "randomcolor";
import Home from "./home";
import { IGlobalStore } from "models/global";
import { randomBg } from "util/color";
+import DemoAtom from "demo-atom";
interface IProps {
store: IGlobalStore;
@@ -18,6 +19,10 @@ export default (props: IProps) => {
Container
{JSON.stringify(props.store, null, 2)}
+
+
+
+
);
};
@@ -30,3 +35,7 @@ const styleContainer = css`
const styleTitle = css`
margin-bottom: 16px;
`;
+
+let styleSpace = css`
+ height: 200px;
+`;
diff --git a/src/use-atom.ts b/src/use-atom.ts
new file mode 100644
index 0000000..81c2c86
--- /dev/null
+++ b/src/use-atom.ts
@@ -0,0 +1,25 @@
+import { useState, useRef } from "react";
+import { produce } from "immer";
+
+/** "Clojure Atom"-like data management for React Hooks */
+export let useAtom = (data: T) => {
+ // state only for triggering changes, data actually hold in dataRef
+ let [state, setState] = useState(data);
+ let dataRef = useRef(data);
+
+ console.log("Atom demo updating");
+
+ return {
+ deref: () => dataRef.current,
+ resetWith: (newData: T) => {
+ dataRef.current = newData;
+ setState(newData);
+ },
+ /** updates with Immer, returns a frozen result */
+ swapWith: (f: (d: T) => T | void) => {
+ let newData = produce(dataRef.current, f) as T;
+ dataRef.current = newData;
+ setState(newData);
+ },
+ };
+};