Skip to content

Commit 04b5164

Browse files
authored
fix: remove useMemo from store built-in hooks (#16)
1 parent 23ab99f commit 04b5164

File tree

12 files changed

+266
-255
lines changed

12 files changed

+266
-255
lines changed

.changeset/gentle-trains-brush.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@fuels/react-xstore': patch
3+
---
4+
5+
Fix: remove `useMemo` from built-in hooks inside store.

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
],
1919
"scripts": {
2020
"build": "turbo run build",
21+
"build:watch": "pnpm -r --parallel build --watch",
2122
"changeset": "changeset",
2223
"changeset:check": "changeset status --since=origin/main",
2324
"changeset:release": "changeset publish --no-git-tag",
@@ -39,22 +40,22 @@
3940
"devDependencies": {
4041
"@jest/types": "^29.6.3",
4142
"@types/jest": "^29.5.4",
42-
"@types/node": "^20.5.4",
43+
"@types/node": "^20.5.9",
4344
"@types/react": "^18.2.21",
4445
"@types/react-dom": "^18.2.7",
4546
"@xstate/cli": "^0.5.2",
4647
"dotenv": "^16.3.1",
47-
"eslint": "^8.47.0",
48+
"eslint": "^8.48.0",
4849
"husky": "^8.0.3",
4950
"jest": "29.6.4",
5051
"lint-staged": "^14.0.1",
5152
"npm-run-all": "^4.1.5",
52-
"prettier": "^3.0.2",
53+
"prettier": "^3.0.3",
5354
"ts-node": "^10.9.1",
5455
"tsup": "^7.2.0",
5556
"turbo": "^1.10.13",
5657
"typescript": "5.2.2",
57-
"updates": "^14.3.5"
58+
"updates": "^14.5.0"
5859
},
5960
"dependencies": {
6061
"@changesets/changelog-github": "^0.4.8",

packages/changeset/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
"dotenv": "^16.3.1"
1414
},
1515
"devDependencies": {
16-
"@types/node": "^20.5.4"
16+
"@types/node": "^20.5.9"
1717
}
1818
}

packages/eslint-plugin/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@
1717
"typescript"
1818
],
1919
"peerDependencies": {
20-
"eslint": "^8.47.0"
20+
"eslint": "^8.48.0"
2121
},
2222
"dependencies": {
2323
"@next/eslint-plugin-next": "^13.4.19",
24-
"@typescript-eslint/eslint-plugin": "^6.4.1",
25-
"@typescript-eslint/parser": "^6.4.1",
26-
"eslint": "^8.47.0",
24+
"@typescript-eslint/eslint-plugin": "^6.6.0",
25+
"@typescript-eslint/parser": "^6.6.0",
26+
"eslint": "^8.48.0",
2727
"eslint-config-prettier": "^9.0.0",
2828
"eslint-import-resolver-node": "^0.3.9",
2929
"eslint-import-resolver-typescript": "^3.6.0",
3030
"eslint-plugin-eslint-comments": "^3.2.0",
3131
"eslint-plugin-import": "^2.28.1",
32-
"eslint-plugin-jest-dom": "^5.0.2",
32+
"eslint-plugin-jest-dom": "^5.1.0",
3333
"eslint-plugin-jsx-a11y": "^6.7.1",
3434
"eslint-plugin-prettier": "^5.0.0",
3535
"eslint-plugin-react": "^7.33.2",
3636
"eslint-plugin-react-hooks": "^4.6.0",
3737
"eslint-plugin-testing-library": "^6.0.1",
38-
"prettier": "^3.0.2"
38+
"prettier": "^3.0.3"
3939
}
4040
}

packages/jest/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
"@fuels/ts-config": "workspace:*",
6363
"@fuels/tsup-config": "workspace:*",
6464
"@jest/types": "^29.6.3",
65-
"@swc/core": "^1.3.78",
65+
"@swc/core": "^1.3.82",
6666
"@swc/jest": "^0.2.29",
6767
"@types/jest-axe": "^3.5.5"
6868
},

packages/prettier-config/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
"main": "./index.json",
66
"access": "public",
77
"dependencies": {
8-
"prettier": "^3.0.2"
8+
"prettier": "^3.0.3"
99
},
1010
"peerDependencies": {
11-
"prettier": "^3.0.2"
11+
"prettier": "^3.0.3"
1212
}
1313
}

packages/react-xstore/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"@xstate/inspect": "^0.8.0",
3838
"@xstate/react": "^3.2.2",
3939
"fast-equals": "^5.0.1",
40-
"jotai": "^2.4.0",
40+
"jotai": "^2.4.1",
4141
"react": "^18.2.0",
4242
"react-dom": "^18.2.0",
4343
"uuid": "^9.0.0",
@@ -48,7 +48,7 @@
4848
"@fuels/ts-config": "workspace:*",
4949
"@fuels/tsup-config": "workspace:*",
5050
"@testing-library/react": "^14.0.0",
51-
"@types/uuid": "^9.0.2",
51+
"@types/uuid": "^9.0.3",
5252
"jest-localstorage-mock": "^2.4.26"
5353
}
5454
}

packages/react-xstore/src/ReactFactory.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ describe('ReactFactory', () => {
3030
const { result } = renderHook(() => {
3131
return store.useSelector('todos', (state) => state.context.todos);
3232
}, opts);
33+
3334
expect(result.current).toEqual([payload]);
3435
expect(spy).toBeCalledTimes(1);
3536

packages/react-xstore/src/ReactFactory.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useSelector as useSelectorRef } from '@xstate/react';
2-
import { Provider, useAtom, useAtomValue } from 'jotai';
2+
import { Provider, useAtom, useAtomValue, useSetAtom } from 'jotai';
33
import type { ReactNode } from 'react';
4-
import { useMemo, useEffect } from 'react';
4+
import { useEffect } from 'react';
55
import type { InterpreterFrom, StateFrom } from 'xstate';
66

77
import type { CreateStoreAtomsReturn } from './atoms';
@@ -40,7 +40,7 @@ export class ReactFactory<T extends MachinesObj> {
4040
// ---------------------------------------------------------------------------
4141

4242
private createUseSelector() {
43-
const { serviceAtom } = this.atoms;
43+
const { servicesAtom } = this.atoms;
4444
/**
4545
* A hook to be used as selector for a specific service.
4646
* @param key The key of the service to select from.
@@ -49,18 +49,19 @@ export class ReactFactory<T extends MachinesObj> {
4949
* @example
5050
* const count = useSelector('counter', (state) => state.context.count);
5151
*/
52+
5253
return function useSelector<K extends keyof T, R>(
5354
key: K,
5455
selector: (state: StateFrom<T[K]>) => R,
5556
) {
56-
const atom = useMemo(() => serviceAtom(key), [key]);
57-
const service = useAtomValue(atom);
57+
const services = useAtomValue(servicesAtom);
58+
const service = services[key];
5859
return useSelectorRef(service, selector) as R;
5960
};
6061
}
6162

6263
private createUseService() {
63-
const { serviceAtom } = this.atoms;
64+
const { servicesAtom } = this.atoms;
6465
/**
6566
* A hook to be used to get a specific service.
6667
* @param key The key of the service to get.
@@ -69,8 +70,8 @@ export class ReactFactory<T extends MachinesObj> {
6970
* const service = useService('counter');
7071
*/
7172
return function useService<K extends keyof T>(key: K) {
72-
const atom = useMemo(() => serviceAtom(key), [key]);
73-
return useAtomValue(atom);
73+
const services = useAtomValue(servicesAtom);
74+
return services[key];
7475
};
7576
}
7677

@@ -84,13 +85,15 @@ export class ReactFactory<T extends MachinesObj> {
8485
* const [state, send] = useState('counter');
8586
*/
8687
return function useState<K extends keyof T>(key: K) {
87-
const atom = useMemo(() => stateAtom(key), [key]);
88-
return useAtom(atom) as [StateFrom<T[K]>, InterpreterFrom<T[K]>['send']];
88+
return useAtom(stateAtom(key)) as [
89+
StateFrom<T[K]>,
90+
InterpreterFrom<T[K]>['send'],
91+
];
8992
};
9093
}
9194

9295
private createUseUpdateMachineConfig() {
93-
const { serviceAtom } = this.atoms;
96+
const { servicesAtom, serviceAtom } = this.atoms;
9497
/**
9598
* A hook to be used to update a specific service config.
9699
* @param key The key of the service to update.
@@ -105,11 +108,14 @@ export class ReactFactory<T extends MachinesObj> {
105108
key: K,
106109
opts: Partial<AddMachineInput<T, K>['getOptions']> = {},
107110
) {
108-
const atom = useMemo(() => serviceAtom(key), [key]);
109-
const [service, updateService] = useAtom(atom);
111+
const updateService = useSetAtom(serviceAtom(key));
112+
const services = useAtomValue(servicesAtom);
113+
const service = services[key];
114+
110115
useEffect(() => {
111116
updateService(opts);
112117
}, [opts, key]);
118+
113119
return service as InterpreterFrom<T[K]>;
114120
};
115121
}

packages/react-xstore/src/atoms/stateAtom.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { atom } from 'jotai';
2-
import type { InterpreterFrom } from 'xstate';
2+
import { atomFamily } from 'jotai/utils';
3+
import type { InterpreterFrom, StateFrom } from 'xstate';
34

45
import type { MachinesObj } from '../types';
56

6-
import type { MachinesAtom } from './machinesAtom';
77
import type { ServiceAtom } from './serviceAtom';
88

99
/**
@@ -14,23 +14,23 @@ import type { ServiceAtom } from './serviceAtom';
1414
* const [state, send] = useAtom(stateAtom('counter'));
1515
*/
1616
export function createStateAtom<T extends MachinesObj>(
17-
machinesAtom: MachinesAtom<T>,
1817
serviceAtom: ServiceAtom<T>,
1918
) {
20-
return <K extends keyof T>(key: keyof T) => {
21-
type Service = InterpreterFrom<T[K]>;
19+
return atomFamily((key: keyof T) => {
20+
type Machine = T[keyof T];
21+
type Service = InterpreterFrom<Machine>;
2222
type Event = Parameters<Service['send']>[0];
2323
return atom(
2424
(get) => {
25-
const machineAtom = get(machinesAtom)[key];
26-
return get(get(machineAtom).atoms.state);
25+
const service = get(serviceAtom(key));
26+
return service.getSnapshot() as StateFrom<Machine>;
2727
},
2828
(get, _set, ev: Event) => {
2929
const service = get(serviceAtom(key));
3030
service.send(ev);
3131
},
3232
);
33-
};
33+
});
3434
}
3535
export type StateAtom<T extends MachinesObj> = ReturnType<
3636
typeof createStateAtom<T>

packages/react-xstore/src/atoms/storeAtoms.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function createStoreAtoms<T extends MachinesObj>(id: string) {
3636
const serviceAtom = createServiceAtom(machinesAtom);
3737
const servicesAtom = createServicesAtom(keysAtom, serviceAtom);
3838
const waitForAtom = createWaitForAtom(serviceAtom);
39-
const stateAtom = createStateAtom(machinesAtom, serviceAtom);
39+
const stateAtom = createStateAtom(serviceAtom);
4040
const onStateChangeAtom = createOnStateChangeAtom<T>();
4141
const onStoreStartAtom = createStoreStartAtom();
4242
return {

0 commit comments

Comments
 (0)