Skip to content

Commit 2567f7b

Browse files
authored
Initial commit (#2)
* initial commit * adding some more comments to the project * initial commit * Update dependencies and use local tgz package in key-value-state-container-react * small refactoring
1 parent 01b8445 commit 2567f7b

File tree

4 files changed

+71
-18
lines changed

4 files changed

+71
-18
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,11 @@ as `statePath` is not including `status` attribute.
6767

6868
- remove all `node_modules` folders manually
6969
- make necessary changes to `key-value-state-container` and bump the version temporarily up (e.g. `1.0.5` -> `1.0.6`)
70-
- run `npm run pack` to create a tgz package locally
70+
- run `npm run pack` in `key-value-state-container` to create a tgz package locally in `~` folder
71+
- change `package.json` in `key-value-state-container-react` to use the local tgz package:
72+
```js
73+
"dependencies": {
74+
"key-value-state-container": "file:~/key-value-state-container-1.0.0.tgz",
75+
}
76+
```
7177
- don't forget to bump the version back to the original one (e.g. `1.0.6` -> `1.0.3`)

src/ContainerRoot/ContainerRoot.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,24 +39,26 @@ export const ContainerRoot = <TState extends Object, TAction extends Action>(
3939
) => {
4040
const [autoContainerId] = useState<string>(getUniqueId());
4141
const {
42+
autoActions,
43+
autoState,
4244
children,
4345
config,
4446
containerId = autoContainerId,
45-
dispatcher,
4647
initialState,
47-
reducer,
4848
persistence,
49+
reducer,
4950
} = props;
5051
const runningFirstTimeRef = useRef<boolean>(true);
5152
if (runningFirstTimeRef.current) {
5253
runningFirstTimeRef.current = false;
5354
registerStateContainer({
55+
autoActions,
56+
autoState,
5457
config,
5558
containerId,
56-
dispatcher,
5759
initialState,
58-
reducer,
5960
persistence,
61+
reducer,
6062
});
6163
}
6264

@@ -68,12 +70,13 @@ export const ContainerRoot = <TState extends Object, TAction extends Action>(
6870
*/
6971
if (reRegister({ containerId })) {
7072
registerStateContainer({
73+
autoActions,
74+
autoState,
7175
config,
7276
containerId,
73-
dispatcher,
7477
initialState,
75-
reducer,
7678
persistence,
79+
reducer,
7780
});
7881
}
7982
return () => {

src/use-dispatch-action.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import { useContext } from "react";
2626
import { Action, dispatchAction } from "key-value-state-container";
2727

28-
import { UseDispatchAction } from "types/contracts";
28+
import { UseDispatchAction } from "./types/contracts";
2929
import {
3030
ContainerRootContext,
3131
ContainerRootContextProps,

src/use-selector.ts

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import { useEffect, useRef, useState } from "react";
2-
import {
2+
import {
33
Action,
4+
ClientNotificationCallbackArgs,
45
getContainer,
6+
getUniqueId,
57
registerStateChangedCallback,
68
TKnownStatePath,
79
unregisterStateChangedCallback,
8-
getUniqueId,
910
} from "key-value-state-container";
1011
import { useGetContainerId } from "./use-get-container-id";
1112
import { RendersWithContainerId } from "./types/contracts";
1213

13-
interface Args<TState extends Object> extends Partial<RendersWithContainerId> {
14+
interface Args<TState extends Object, TAction extends Action = Action>
15+
extends Partial<RendersWithContainerId> {
16+
callback?: (args: ClientNotificationCallbackArgs<TState, TAction>) => void;
1417
/**
1518
* Diagnostics flag that helps to identify problems
1619
* @default true
@@ -25,15 +28,40 @@ interface Args<TState extends Object> extends Partial<RendersWithContainerId> {
2528
*/
2629
lateInvoke?: boolean;
2730
listenerTag?: string;
28-
statePath: TKnownStatePath<TState>[];
31+
32+
statePath: TKnownStatePath<TState>[] | TKnownStatePath<TState>;
33+
34+
/**
35+
* When `true`, selector code will be not active (will not register any callback)
36+
* and always return the current container state (as it is), so the hook will no
37+
* longer be a hook, but a simple function.
38+
*
39+
* Reason for introduction: it is not possible to have code that calls hooks
40+
* conditionally, as this will violate rules of hooks, so this is a workaround.
41+
* So, in other words, it is not possible to have something like this:
42+
*
43+
* ```
44+
* if (hookNonNecessary) {
45+
* return;
46+
* }
47+
* const result = useHook();
48+
* ```
49+
* The purpose is to makes code more linear and easier to maintain.
50+
*/
51+
switchOff?: boolean;
2952
}
3053

31-
export const useSelector = <TState extends Object, TAction extends Action>({
54+
export const useSelector = <
55+
TState extends Object,
56+
TAction extends Action = Action
57+
>({
58+
callback,
3259
containerId: containerIdFromProps,
3360
ignoreUnregistered,
34-
lateInvoke,
61+
lateInvoke: lateInvokeFromProps,
3562
listenerTag,
3663
statePath,
64+
switchOff,
3765
}: Args<TState>) => {
3866
const listenerIdRef = useRef<string>(
3967
`${listenerTag ? `${listenerTag}:` : ""}${getUniqueId()}`
@@ -47,22 +75,31 @@ export const useSelector = <TState extends Object, TAction extends Action>({
4775
ignoreUnregistered:
4876
typeof ignoreUnregistered === "boolean" ? ignoreUnregistered : true,
4977
}) || {};
78+
const lateInvoke =
79+
typeof lateInvokeFromProps === "boolean" ? lateInvokeFromProps : true;
5080
const [currentState, setCurrentState] = useState(initialState);
5181
useEffect(() => {
5282
return () => {
5383
unmountedRef.current = true;
5484
};
5585
}, []);
5686
useEffect(() => {
87+
if (switchOff) {
88+
return;
89+
}
90+
const statePaths =
91+
typeof statePath === "string"
92+
? [statePath]
93+
: (statePath as TKnownStatePath<TState>[]);
5794
const statePathsLookup: Record<
5895
TKnownStatePath<TState>,
5996
true
60-
> = statePath.reduce((acc, path) => {
97+
> = statePaths.reduce((acc, path) => {
6198
acc[path] = true;
6299
return acc;
63100
}, {} as Record<TKnownStatePath<TState>, true>);
64101
registerStateChangedCallback<TState, TAction>({
65-
callback: ({ changedPaths, newState }) => {
102+
callback: ({ action, changedPaths, newState, oldState }) => {
66103
/**
67104
* Prevent receiving this React warning
68105
* "Can't perform a React state update on an unmounted component.
@@ -79,15 +116,22 @@ export const useSelector = <TState extends Object, TAction extends Action>({
79116
) {
80117
setCurrentState(newState);
81118
}
119+
if (callback) {
120+
callback({ action, changedPaths, newState, oldState });
121+
}
82122
},
83-
lateInvoke: typeof lateInvoke === "boolean" ? lateInvoke : true,
84-
listenerId: listenerIdRef.current,
85123
containerId,
124+
lateInvoke,
125+
listenerId: listenerIdRef.current,
86126
statePath: "*",
87127
});
88128
return () => {
129+
if (switchOff) {
130+
return;
131+
}
89132
unregisterStateChangedCallback<TState>({
90133
containerId,
134+
lateInvoke,
91135
listenerId: listenerIdRef.current,
92136
statePath: "*",
93137
});

0 commit comments

Comments
 (0)