Skip to content

Commit 498da68

Browse files
committed
[WIP] useProxyState hook
1 parent 29aa868 commit 498da68

15 files changed

Lines changed: 152 additions & 94 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { memo, useCallback } from "react";
2+
import { useProxyState } from "../../../../../../packages/react-tools/src";
3+
4+
/**
5+
DEMO
6+
*/
7+
const Child1 = memo(({ state, onClick }: { state: number, onClick: ()=>void }) => {
8+
return (<>
9+
<p>Num value is: {state}</p>
10+
<button onClick={onClick} type={'button'}>Increment</button>
11+
</>);
12+
});
13+
14+
const Child2 = memo(({ state, onClick }: { state: string, onClick: () => void }) => {
15+
return (<>
16+
<p>Random value is: {state}</p>
17+
<button onClick={onClick} type={'button'}>
18+
Change random
19+
</button>
20+
</>);
21+
});
22+
23+
const UseProxyState = () => {
24+
const state = useProxyState({ num: 0, nested: { random: "" } }, true);
25+
const increment = useCallback(() => state.num++, [state.num]);
26+
const random = useCallback(() => state.nested.random = Math.random().toFixed(2), [state.nested]);
27+
return (
28+
<div>
29+
<p>
30+
Current Value (in the proxy state): {state.num} - random: {state.nested.random}
31+
</p>
32+
<Child1 state={state.num} onClick={increment}/>
33+
<Child2 state={state.nested.random} onClick={random} />
34+
</div>
35+
);
36+
}
37+
38+
UseProxyState.displayName = "UseProxyState";
39+
40+
export { UseProxyState };

apps/react-tools-demo/src/constants/components.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const COMPONENTS = [
1212
"useMap",
1313
"useSet",
1414
"useArray",
15+
"useProxyState",
1516
"useMemoizedFunction",
1617
"useMemoCompare",
1718
"useMemoDeepCompare",
@@ -31,6 +32,5 @@ export const COMPONENTS = [
3132
"isTouchEvent",
3233
"isMouseEvent",
3334
"isClient",
34-
"isPlainObject"
3535
]
3636
]

apps/react-tools-demo/src/markdown/useArray.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# useArray
2-
Hooks to use _Array data structure_ to handle component state with all Array methods.
2+
Hook to use _Array data structure_ to handle component state with all Array methods.
33

44
## Usage
55

@@ -17,10 +17,6 @@ const UseArray = () => {
1717
array.push(inputRef.current!.value);
1818
}, [array]);
1919

20-
const concat = useCallback(() => {
21-
array.concat(inputRef.current!.value);
22-
}, [array]);
23-
2420
return (<>
2521
{array.join(",")}
2622
<br />
@@ -29,7 +25,6 @@ const UseArray = () => {
2925
<div style={{ marginTop: 15, gridTemplateColumns: 'auto auto', justifyContent: 'center', display: 'grid', gap: '5px' }}>
3026
<button onClick={push}>Push</button>
3127
<button onClick={pop}>Pop</button>
32-
<button onClick={concat}>Concat</button>
3328
</div>
3429
</>);
3530
}
@@ -44,7 +39,6 @@ export { UseArray }
4439
> - An uncontrolled input with _inputRef_ ref used to execute buttons actions.
4540
> - A button _Push_ that push the input value into state by _push_ method of Array interface.
4641
> - A button _Pop_ that remove last item into state by _pop_ method of Array interface.
47-
> - A button _Concat_ that concats the input value with state by _concat_ method of Array interface.
4842
4943

5044
## API

apps/react-tools-demo/src/markdown/useMap.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# useMap
2-
Hooks to use _Map data structure_ to handle component state with all Map methods.
2+
Hook to use _Map data structure_ to handle component state with all Map methods.
33

44
## Usage
55

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# useProxyState
2+
Hook to handle component state that allows you to use an object for your state and mutating it in a way more idiomatic for JS.
3+
4+
## Usage
5+
6+
```tsx
7+
const Child1 = memo(({ state }: { state: { num: number[], nested: { random: string } } }) => {
8+
const onClick = useCallback(() => state.num.push(Math.random()), [state.num]);
9+
return (<>
10+
<p>Num value is: {state.num}</p>
11+
<button onClick={onClick} type={'button'}>Increment</button>
12+
</>);
13+
});
14+
15+
const Child2 = memo(({ state }: { state: { num: number[], nested: {random: string} } }) => {
16+
const onClick = useCallback(() => state.nested = {random: String(Math.round(Math.random() * 1000))}, [state]);
17+
return (<>
18+
<p>Random value is: {state.nested.random}</p>
19+
<button onClick={onClick} type={'button'}>
20+
Change random
21+
</button>
22+
</>);
23+
});
24+
25+
const UseProxyState = () => {
26+
const state = useProxyState({ num: [], nested: { random: "" } });
27+
28+
return (
29+
<div>
30+
<p>
31+
Current Value (in the proxy state): {state.num} - random: {state.nested.random}
32+
</p>
33+
<Child1 state={state}/>
34+
<Child2 state={state}/>
35+
</div>
36+
);
37+
}
38+
39+
UseProxyState.displayName = "UseProxyState";
40+
41+
export { UseProxyState };
42+
```
43+
44+
> DEMO
45+
46+
47+
## API
48+
49+
```tsx
50+
useProxyState
51+
```
52+
53+
> ### Params
54+
>
55+
> - __initialState__: _T | () => T_
56+
value or function
57+
> - __proxyInDepth=false?__: _boolean_
58+
if true, it creates proxy for nested object also.
59+
>
60+
61+
> ### Returns
62+
>
63+
> __state__
64+
> - _T_
65+
>

apps/react-tools-demo/src/markdown/useSet.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# useSet
2-
Hooks to use _Set data structure_ to handle component state with all Set methods.
2+
Hook to use _Set data structure_ to handle component state with all Set methods.
33

44
## Usage
55

apps/react-tools-demo/src/router/Router.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ import isDeepEqualMD from '../markdown/isDeepEqual.md?url';
2525
import isMouseEventMD from '../markdown/isMouseEvent.md?url';
2626
import isTouchEventMD from '../markdown/isTouchEvent.md?url';
2727
import isClientMD from '../markdown/isClient.md?url';
28-
import isPlainObjectMD from '../markdown/isPlainObject.md?url';
2928
import usePubSubModelMD from '../markdown/usePubSubModel.md?url';
3029
import useEventDispatcherMD from '../markdown/useEventDispatcher.md?url';
3130
import useLocalStorageStateMD from '../markdown/useLocalStorageState.md?url';
3231
import useSessionStorageStateMD from '../markdown/useSessionStorageState.md?url';
3332
import useMapMD from '../markdown/useMap.md?url';
3433
import useSetMD from '../markdown/useSet.md?url';
3534
import useArrayMD from '../markdown/useArray.md?url';
35+
import useProxyStateMD from '../markdown/useProxyState.md?url';
3636
import { UsePrevious } from '../components/hooks/usePrevious/UsePrevious';
3737
import { UseStateHistory } from '../components/hooks/useStateHistory/UseStateHistory';
3838
import { UseCallbackCompare } from '../components/hooks/useCallbackCompare/UseCallbackCompare';
@@ -51,6 +51,7 @@ import { UseEventDispatcher } from '../components/hooks/useEventDispatcher/UseEv
5151
import { UseMap } from '../components/hooks/useMap/UseMap';
5252
import { UseSet } from '../components/hooks/useSet/UseSet';
5353
import { UseArray } from '../components/hooks/useArray/UseArray';
54+
import { UseProxyState } from '../components/hooks/useProxyState/UseProxyState';
5455

5556
function Router() {
5657
const router = createBrowserRouter([
@@ -142,6 +143,13 @@ function Router() {
142143
markdown={useArrayMD}
143144
/>
144145
},
146+
{
147+
path: "/useProxyState",
148+
element: <ComponentLayout
149+
component={<UseProxyState />}
150+
markdown={useProxyStateMD}
151+
/>
152+
},
145153
{
146154
path: "/useMemoizedFunction",
147155
element: <ComponentLayout
@@ -253,11 +261,6 @@ function Router() {
253261
element: <MarkdownLayout
254262
source={isClientMD}
255263
/>
256-
},
257-
{
258-
path: "/isPlainObject",
259-
element: <MarkdownLayout source={isPlainObjectMD}
260-
/>
261264
}
262265
]
263266
}

packages/react-tools/src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export { useSessionStorageState } from './useSessionStorageState';
99
export { useMap } from './useMap';
1010
export { useSet } from './useSet';
1111
export { useArray } from './useArray';
12+
export { useProxyState } from './useProxyState';
1213
export { useMemoizedFunction } from './useMemoizedFunction';
1314
export { useMemoCompare } from "./useMemoCompare";
1415
export { useMemoDeepCompare } from './useMemoDeepCompare';

packages/react-tools/src/hooks/useArray.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from "react"
22

33
/**
4-
* __`useArray`__: Hooks to use _Array data structure_ to handle component state with all Array methods.
4+
* __`useArray`__: Hook to use _Array data structure_ to handle component state with all Array methods.
55
* @param {Array<T> | (() => Array<T>} [initialState] - An Array or function that returns it.
66
* @returns {Array<T>}
77
*/

packages/react-tools/src/hooks/useMap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from "react"
22

33
/**
4-
* __`useMap`__: Hooks to use _Map data structure_ to handle component state with all Map methods.
4+
* __`useMap`__: Hook to use _Map data structure_ to handle component state with all Map methods.
55
* @param {Iterable<readonly [K, V]> | (() => Iterable<readonly [K, V]>)} [initialState] - An Array or other iterable object whose elements are key-value pairs, or function that returns it.
66
* @returns {Map<K,V>}
77
*/

0 commit comments

Comments
 (0)