@livestore/react 0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +1 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/LiveStoreContext.d.ts +7 -0
  4. package/dist/LiveStoreContext.d.ts.map +1 -0
  5. package/dist/LiveStoreContext.js +13 -0
  6. package/dist/LiveStoreContext.js.map +1 -0
  7. package/dist/LiveStoreProvider.d.ts +49 -0
  8. package/dist/LiveStoreProvider.d.ts.map +1 -0
  9. package/dist/LiveStoreProvider.js +168 -0
  10. package/dist/LiveStoreProvider.js.map +1 -0
  11. package/dist/LiveStoreProvider.test.d.ts +2 -0
  12. package/dist/LiveStoreProvider.test.d.ts.map +1 -0
  13. package/dist/LiveStoreProvider.test.js +62 -0
  14. package/dist/LiveStoreProvider.test.js.map +1 -0
  15. package/dist/__tests__/fixture.d.ts +567 -0
  16. package/dist/__tests__/fixture.d.ts.map +1 -0
  17. package/dist/__tests__/fixture.js +61 -0
  18. package/dist/__tests__/fixture.js.map +1 -0
  19. package/dist/experimental/components/LiveList.d.ts +21 -0
  20. package/dist/experimental/components/LiveList.d.ts.map +1 -0
  21. package/dist/experimental/components/LiveList.js +31 -0
  22. package/dist/experimental/components/LiveList.js.map +1 -0
  23. package/dist/experimental/mod.d.ts +2 -0
  24. package/dist/experimental/mod.d.ts.map +1 -0
  25. package/dist/experimental/mod.js +2 -0
  26. package/dist/experimental/mod.js.map +1 -0
  27. package/dist/mod.d.ts +8 -0
  28. package/dist/mod.d.ts.map +1 -0
  29. package/dist/mod.js +8 -0
  30. package/dist/mod.js.map +1 -0
  31. package/dist/useAtom.d.ts +10 -0
  32. package/dist/useAtom.d.ts.map +1 -0
  33. package/dist/useAtom.js +37 -0
  34. package/dist/useAtom.js.map +1 -0
  35. package/dist/useQuery.d.ts +9 -0
  36. package/dist/useQuery.d.ts.map +1 -0
  37. package/dist/useQuery.js +88 -0
  38. package/dist/useQuery.js.map +1 -0
  39. package/dist/useQuery.test.d.ts +2 -0
  40. package/dist/useQuery.test.d.ts.map +1 -0
  41. package/dist/useQuery.test.js +51 -0
  42. package/dist/useQuery.test.js.map +1 -0
  43. package/dist/useRow.d.ts +46 -0
  44. package/dist/useRow.d.ts.map +1 -0
  45. package/dist/useRow.js +96 -0
  46. package/dist/useRow.js.map +1 -0
  47. package/dist/useRow.test.d.ts +2 -0
  48. package/dist/useRow.test.d.ts.map +1 -0
  49. package/dist/useRow.test.js +212 -0
  50. package/dist/useRow.test.js.map +1 -0
  51. package/dist/useTemporaryQuery.d.ts +22 -0
  52. package/dist/useTemporaryQuery.d.ts.map +1 -0
  53. package/dist/useTemporaryQuery.js +75 -0
  54. package/dist/useTemporaryQuery.js.map +1 -0
  55. package/dist/useTemporaryQuery.test.d.ts +2 -0
  56. package/dist/useTemporaryQuery.test.d.ts.map +1 -0
  57. package/dist/useTemporaryQuery.test.js +59 -0
  58. package/dist/useTemporaryQuery.test.js.map +1 -0
  59. package/dist/utils/stack-info.d.ts +4 -0
  60. package/dist/utils/stack-info.d.ts.map +1 -0
  61. package/dist/utils/stack-info.js +11 -0
  62. package/dist/utils/stack-info.js.map +1 -0
  63. package/dist/utils/useStateRefWithReactiveInput.d.ts +13 -0
  64. package/dist/utils/useStateRefWithReactiveInput.d.ts.map +1 -0
  65. package/dist/utils/useStateRefWithReactiveInput.js +38 -0
  66. package/dist/utils/useStateRefWithReactiveInput.js.map +1 -0
  67. package/package.json +54 -0
  68. package/src/LiveStoreContext.ts +19 -0
  69. package/src/LiveStoreProvider.test.tsx +109 -0
  70. package/src/LiveStoreProvider.tsx +295 -0
  71. package/src/__snapshots__/useRow.test.tsx.snap +359 -0
  72. package/src/__tests__/fixture.tsx +119 -0
  73. package/src/ambient.d.ts +2 -0
  74. package/src/experimental/components/LiveList.tsx +84 -0
  75. package/src/experimental/mod.ts +1 -0
  76. package/src/mod.ts +13 -0
  77. package/src/useAtom.ts +55 -0
  78. package/src/useQuery.test.tsx +82 -0
  79. package/src/useQuery.ts +122 -0
  80. package/src/useRow.test.tsx +346 -0
  81. package/src/useRow.ts +182 -0
  82. package/src/useTemporaryQuery.test.tsx +98 -0
  83. package/src/useTemporaryQuery.ts +131 -0
  84. package/src/utils/stack-info.ts +13 -0
  85. package/src/utils/useStateRefWithReactiveInput.ts +51 -0
  86. package/tsconfig.json +20 -0
  87. package/vitest.config.js +17 -0
@@ -0,0 +1,212 @@
1
+ import * as LiveStore from '@livestore/livestore';
2
+ import { getSimplifiedRootSpan } from '@livestore/livestore/internal/testing-utils';
3
+ import { Effect, ReadonlyRecord, Schema } from '@livestore/utils/effect';
4
+ import * as otel from '@opentelemetry/api';
5
+ import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
6
+ import { render, renderHook } from '@testing-library/react';
7
+ import React from 'react';
8
+ import { describe, expect, it } from 'vitest';
9
+ import { AppComponentSchema, AppRouterSchema, makeTodoMvcReact, tables, todos } from './__tests__/fixture.js';
10
+ import * as LiveStoreReact from './mod.js';
11
+ // NOTE running tests concurrently doesn't work with the default global db graph
12
+ describe('useRow', () => {
13
+ it('should update the data based on component key', () => Effect.gen(function* () {
14
+ const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
15
+ useGlobalReactivityGraph: false,
16
+ });
17
+ const renderCount = makeRenderCount();
18
+ const { result, rerender } = renderHook((userId) => {
19
+ renderCount.inc();
20
+ const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
21
+ return { state, setState };
22
+ }, { wrapper, initialProps: 'u1' });
23
+ expect(result.current.state.id).toBe('u1');
24
+ expect(result.current.state.username).toBe('');
25
+ expect(renderCount.val).toBe(1);
26
+ React.act(() => store.mutate(LiveStore.rawSqlMutation({
27
+ sql: LiveStore.sql `INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
28
+ })));
29
+ rerender('u2');
30
+ expect(result.current.state.id).toBe('u2');
31
+ expect(result.current.state.username).toBe('username_u2');
32
+ expect(renderCount.val).toBe(2);
33
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
34
+ // TODO add a test that makes sure React doesn't re-render when a setter is used to set the same value
35
+ it('should update the data reactively - via setState', () => Effect.gen(function* () {
36
+ const { wrapper, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
37
+ useGlobalReactivityGraph: false,
38
+ });
39
+ const renderCount = makeRenderCount();
40
+ const { result } = renderHook((userId) => {
41
+ renderCount.inc();
42
+ const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
43
+ return { state, setState };
44
+ }, { wrapper, initialProps: 'u1' });
45
+ expect(result.current.state.id).toBe('u1');
46
+ expect(result.current.state.username).toBe('');
47
+ expect(renderCount.val).toBe(1);
48
+ React.act(() => result.current.setState.username('username_u1_hello'));
49
+ expect(result.current.state.id).toBe('u1');
50
+ expect(result.current.state.username).toBe('username_u1_hello');
51
+ expect(renderCount.val).toBe(2);
52
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
53
+ it('should update the data reactively - via raw store mutation', () => Effect.gen(function* () {
54
+ const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
55
+ useGlobalReactivityGraph: false,
56
+ });
57
+ const renderCount = makeRenderCount();
58
+ const { result } = renderHook((userId) => {
59
+ renderCount.inc();
60
+ const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
61
+ return { state, setState };
62
+ }, { wrapper, initialProps: 'u1' });
63
+ expect(result.current.state.id).toBe('u1');
64
+ expect(result.current.state.username).toBe('');
65
+ expect(renderCount.val).toBe(1);
66
+ React.act(() => store.mutate(LiveStore.rawSqlMutation({
67
+ sql: LiveStore.sql `UPDATE UserInfo SET username = 'username_u1_hello' WHERE id = 'u1';`,
68
+ })));
69
+ expect(result.current.state.id).toBe('u1');
70
+ expect(result.current.state.username).toBe('username_u1_hello');
71
+ expect(renderCount.val).toBe(2);
72
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
73
+ it('should work for a larger app', () => Effect.gen(function* () {
74
+ const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
75
+ useGlobalReactivityGraph: false,
76
+ });
77
+ const allTodos$ = LiveStore.querySQL(`select * from todos`, {
78
+ label: 'allTodos',
79
+ schema: Schema.Array(tables.todos.schema),
80
+ reactivityGraph,
81
+ });
82
+ const appRouterRenderCount = makeRenderCount();
83
+ let globalSetState;
84
+ const AppRouter = () => {
85
+ appRouterRenderCount.inc();
86
+ const [state, setState] = LiveStoreReact.useRow(AppRouterSchema, { reactivityGraph });
87
+ globalSetState = setState;
88
+ return (React.createElement("div", null,
89
+ React.createElement(TasksList, { setTaskId: setState.currentTaskId }),
90
+ React.createElement("div", { role: "current-id" },
91
+ "Current Task Id: ",
92
+ state.currentTaskId ?? '-'),
93
+ state.currentTaskId ? React.createElement(TaskDetails, { id: state.currentTaskId }) : React.createElement("div", null, "Click on a task to see details")));
94
+ };
95
+ const TasksList = ({ setTaskId }) => {
96
+ const allTodos = LiveStoreReact.useQuery(allTodos$);
97
+ return (React.createElement("div", null, allTodos.map((_) => (React.createElement("div", { key: _.id, onClick: () => setTaskId(_.id) }, _.id)))));
98
+ };
99
+ const TaskDetails = ({ id }) => {
100
+ const [todo] = LiveStoreReact.useRow(todos, id, { reactivityGraph });
101
+ return React.createElement("div", { role: "content" }, JSON.stringify(todo));
102
+ };
103
+ const renderResult = render(React.createElement(AppRouter, null), { wrapper });
104
+ expect(appRouterRenderCount.val).toBe(1);
105
+ React.act(() => store.mutate(LiveStore.rawSqlMutation({
106
+ sql: LiveStore.sql `INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)`,
107
+ })));
108
+ expect(appRouterRenderCount.val).toBe(1);
109
+ expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: -"');
110
+ React.act(() => globalSetState.currentTaskId('t1'));
111
+ expect(appRouterRenderCount.val).toBe(2);
112
+ expect(renderResult.getByRole('content').innerHTML).toMatchInlineSnapshot(`"{"id":"t1","text":"buy milk","completed":false}"`);
113
+ expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: t1"');
114
+ React.act(() => store.mutate(LiveStore.rawSqlMutation({
115
+ sql: LiveStore.sql `INSERT INTO todos (id, text, completed) VALUES ('t2', 'buy eggs', 0)`,
116
+ }), AppRouterSchema.update({ where: { id: 'singleton' }, values: { currentTaskId: 't2' } }), LiveStore.rawSqlMutation({
117
+ sql: LiveStore.sql `INSERT INTO todos (id, text, completed) VALUES ('t3', 'buy bread', 0)`,
118
+ })));
119
+ expect(appRouterRenderCount.val).toBe(3);
120
+ expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: t2"');
121
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
122
+ it('should work for a useRow query chained with a useTemporary query', () => Effect.gen(function* () {
123
+ const { store, wrapper, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
124
+ useGlobalReactivityGraph: false,
125
+ });
126
+ const renderCount = makeRenderCount();
127
+ store.mutate(todos.insert({ id: 't1', text: 'buy milk', completed: false }), todos.insert({ id: 't2', text: 'buy bread', completed: false }));
128
+ const { result, unmount, rerender } = renderHook((userId) => {
129
+ renderCount.inc();
130
+ const [_row, _setRow, rowState$] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
131
+ const todos = LiveStoreReact.useTemporaryQuery(() => LiveStore.querySQL((get) => LiveStore.sql `select * from todos where text like '%${get(rowState$).text}%'`, {
132
+ schema: Schema.Array(tables.todos.schema),
133
+ reactivityGraph,
134
+ label: 'todosFiltered',
135
+ }), userId);
136
+ return { todos };
137
+ }, { wrapper, initialProps: 'u1' });
138
+ React.act(() => store.mutate(LiveStore.rawSqlMutation({
139
+ sql: LiveStore.sql `INSERT INTO UserInfo (id, username, text) VALUES ('u2', 'username_u2', 'milk')`,
140
+ })));
141
+ expect(result.current.todos.length).toBe(2);
142
+ // expect(result.current.state.username).toBe('')
143
+ expect(renderCount.val).toBe(1);
144
+ rerender('u2');
145
+ expect(result.current.todos.length).toBe(1);
146
+ expect(renderCount.val).toBe(2);
147
+ unmount();
148
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
149
+ let cachedProvider;
150
+ describe('otel', () => {
151
+ const exporter = new InMemorySpanExporter();
152
+ const provider = cachedProvider ?? new BasicTracerProvider();
153
+ cachedProvider = provider;
154
+ provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
155
+ provider.register();
156
+ const otelTracer = otel.trace.getTracer('test');
157
+ const span = otelTracer.startSpan('test');
158
+ const otelContext = otel.trace.setSpan(otel.context.active(), span);
159
+ it('should update the data based on component key', async () => {
160
+ const { strictMode } = await Effect.gen(function* () {
161
+ const { wrapper, store, reactivityGraph, makeRenderCount, strictMode } = yield* makeTodoMvcReact({
162
+ useGlobalReactivityGraph: false,
163
+ otelContext,
164
+ otelTracer,
165
+ });
166
+ const renderCount = makeRenderCount();
167
+ const { result, rerender, unmount } = renderHook((userId) => {
168
+ renderCount.inc();
169
+ const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
170
+ return { state, setState };
171
+ }, { wrapper, initialProps: 'u1' });
172
+ expect(result.current.state.id).toBe('u1');
173
+ expect(result.current.state.username).toBe('');
174
+ expect(renderCount.val).toBe(1);
175
+ React.act(() => store.mutate(LiveStore.rawSqlMutation({
176
+ sql: LiveStore.sql `INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
177
+ })));
178
+ rerender('u2');
179
+ expect(result.current.state.id).toBe('u2');
180
+ expect(result.current.state.username).toBe('username_u2');
181
+ expect(renderCount.val).toBe(2);
182
+ unmount();
183
+ span.end();
184
+ return { strictMode };
185
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise);
186
+ const mapAttributes = (attributes) => {
187
+ return ReadonlyRecord.map(attributes, (val, key) => {
188
+ if (key === 'stackInfo') {
189
+ const stackInfo = JSON.parse(val);
190
+ // stackInfo.frames.shift() // Removes `renderHook.wrapper` from the stack
191
+ stackInfo.frames.forEach((_) => {
192
+ if (_.name.includes('renderHook.wrapper')) {
193
+ _.name = 'renderHook.wrapper';
194
+ }
195
+ _.filePath = '__REPLACED_FOR_SNAPSHOT__';
196
+ });
197
+ return JSON.stringify(stackInfo);
198
+ }
199
+ return val;
200
+ });
201
+ };
202
+ // TODO improve testing setup so "obsolete" warning is avoided
203
+ if (strictMode) {
204
+ expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot('strictMode=true');
205
+ }
206
+ else {
207
+ expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot('strictMode=false');
208
+ }
209
+ });
210
+ });
211
+ });
212
+ //# sourceMappingURL=useRow.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRow.test.js","sourceRoot":"","sources":["../src/useRow.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { QueryInfo } from '@livestore/common';
2
+ import type { LiveQuery } from '@livestore/livestore';
3
+ import * as otel from '@opentelemetry/api';
4
+ import React from 'react';
5
+ export type DepKey = string | number | ReadonlyArray<string | number>;
6
+ /**
7
+ * Creates a query, subscribes and destroys it when the component unmounts.
8
+ *
9
+ * The `key` is used to determine whether the a new query should be created or if the existing one should be reused.
10
+ */
11
+ export declare const useTemporaryQuery: <TResult>(makeQuery: () => LiveQuery<TResult>, key: DepKey) => TResult;
12
+ export declare const useTemporaryQueryRef: <TResult>(makeQuery: () => LiveQuery<TResult>, key: DepKey) => React.MutableRefObject<TResult>;
13
+ export declare const useMakeTemporaryQuery: <TResult, TQueryInfo extends QueryInfo>(makeQuery: (otelContext: otel.Context) => LiveQuery<TResult, TQueryInfo>, key: DepKey, options?: {
14
+ otel?: {
15
+ spanName?: string;
16
+ attributes?: otel.Attributes;
17
+ };
18
+ }) => {
19
+ query$: LiveQuery<TResult, TQueryInfo>;
20
+ otelContext: otel.Context;
21
+ };
22
+ //# sourceMappingURL=useTemporaryQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemporaryQuery.d.ts","sourceRoot":"","sources":["../src/useTemporaryQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAA;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAA;AAuBzB,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;AAErE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,aAAa,MAAM,SAAS,CAAC,OAAO,CAAC,OAAO,MAAM,KAAG,OAChD,CAAA;AAE9C,eAAO,MAAM,oBAAoB,GAAI,OAAO,aAC/B,MAAM,SAAS,CAAC,OAAO,CAAC,OAC9B,MAAM,KACV,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAIhC,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,OAAO,EAAE,UAAU,SAAS,SAAS,aAC9D,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,OACnE,MAAM,YACD;IACR,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,CAAA;KAC7B,CAAA;CACF,KACA;IAAE,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAA;CA4ErE,CAAA"}
@@ -0,0 +1,75 @@
1
+ import * as otel from '@opentelemetry/api';
2
+ import React from 'react';
3
+ import { useStore } from './LiveStoreContext.js';
4
+ import { useQueryRef } from './useQuery.js';
5
+ // NOTE Given `useMemo` will be called multiple times (e.g. when using React Strict mode or Fast Refresh),
6
+ // we are using this cache to avoid starting multiple queries/spans for the same component.
7
+ // This is somewhat against some recommended React best practices, but it should be fine in our case below.
8
+ // Please definitely open an issue if you see or run into any problems with this approach!
9
+ const cache = new Map();
10
+ /**
11
+ * Creates a query, subscribes and destroys it when the component unmounts.
12
+ *
13
+ * The `key` is used to determine whether the a new query should be created or if the existing one should be reused.
14
+ */
15
+ export const useTemporaryQuery = (makeQuery, key) => useTemporaryQueryRef(makeQuery, key).current;
16
+ export const useTemporaryQueryRef = (makeQuery, key) => {
17
+ const { query$ } = useMakeTemporaryQuery(makeQuery, key);
18
+ return useQueryRef(query$);
19
+ };
20
+ export const useMakeTemporaryQuery = (makeQuery, key, options) => {
21
+ const { store } = useStore();
22
+ const fullKey = React.useMemo(
23
+ // NOTE We're using the `makeQuery` function body string to make sure the key is unique across the app
24
+ // TODO we should figure out whether this could cause some problems and/or if there's a better way to do this
25
+ () => (Array.isArray(key) ? key.join('-') : key) + '-' + store.reactivityGraph.id + '-' + makeQuery.toString(), [key, makeQuery, store.reactivityGraph.id]);
26
+ const fullKeyRef = React.useRef();
27
+ const { query$, otelContext } = React.useMemo(() => {
28
+ if (fullKeyRef.current !== undefined && fullKeyRef.current !== fullKey) {
29
+ // console.debug('fullKey changed', 'prev', fullKeyRef.current.split('-')[0]!, '-> new', fullKey.split('-')[0]!)
30
+ const cachedItem = cache.get(fullKeyRef.current);
31
+ if (cachedItem !== undefined && cachedItem._tag === 'active') {
32
+ cachedItem.rc--;
33
+ if (cachedItem.rc === 0) {
34
+ // console.debug('rc=0-changed', cachedItem.query$.id, cachedItem.query$.label)
35
+ cachedItem.query$.destroy();
36
+ cachedItem.span.end();
37
+ cache.set(fullKeyRef.current, { _tag: 'destroyed' });
38
+ }
39
+ }
40
+ }
41
+ const cachedItem = cache.get(fullKey);
42
+ if (cachedItem !== undefined && cachedItem._tag === 'active') {
43
+ // console.debug('rc++', cachedItem.query$.id, cachedItem.query$.label)
44
+ cachedItem.rc++;
45
+ return cachedItem;
46
+ }
47
+ const spanName = options?.otel?.spanName ?? `LiveStore:useTemporaryQuery:${key}`;
48
+ const span = store.otel.tracer.startSpan(spanName, { attributes: options?.otel?.attributes }, store.otel.queriesSpanContext);
49
+ const otelContext = otel.trace.setSpan(otel.context.active(), span);
50
+ const query$ = makeQuery(otelContext);
51
+ cache.set(fullKey, { _tag: 'active', rc: 1, query$, span, otelContext });
52
+ return { query$, otelContext };
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ }, [fullKey]);
55
+ fullKeyRef.current = fullKey;
56
+ React.useEffect(() => {
57
+ return () => {
58
+ const fullKey = fullKeyRef.current;
59
+ const cachedItem = cache.get(fullKey);
60
+ // NOTE in case the fullKey changed then the query was already destroyed in the useMemo above
61
+ if (cachedItem === undefined || cachedItem._tag === 'destroyed')
62
+ return;
63
+ // console.debug('rc--', cachedItem.query$.id, cachedItem.query$.label)
64
+ cachedItem.rc--;
65
+ if (cachedItem.rc === 0) {
66
+ // console.debug('rc=0', cachedItem.query$.id, cachedItem.query$.label)
67
+ cachedItem.query$.destroy();
68
+ cachedItem.span.end();
69
+ cache.delete(fullKey);
70
+ }
71
+ };
72
+ }, []);
73
+ return { query$, otelContext };
74
+ };
75
+ //# sourceMappingURL=useTemporaryQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemporaryQuery.js","sourceRoot":"","sources":["../src/useTemporaryQuery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useTemporaryQuery.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemporaryQuery.test.d.ts","sourceRoot":"","sources":["../src/useTemporaryQuery.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import * as LiveStore from '@livestore/livestore';
2
+ import { querySQL } from '@livestore/livestore';
3
+ import { Effect, Schema } from '@livestore/utils/effect';
4
+ import { render, renderHook } from '@testing-library/react';
5
+ import React from 'react';
6
+ // @ts-expect-error no types
7
+ import * as ReactWindow from 'react-window';
8
+ import { describe, expect, it } from 'vitest';
9
+ import { makeTodoMvcReact, tables, todos } from './__tests__/fixture.js';
10
+ import * as LiveStoreReact from './mod.js';
11
+ describe('useTemporaryQuery', () => {
12
+ it('simple', () => Effect.gen(function* () {
13
+ const { wrapper, store, makeRenderCount } = yield* makeTodoMvcReact();
14
+ const renderCount = makeRenderCount();
15
+ store.mutate(todos.insert({ id: 't1', text: 'buy milk', completed: false }), todos.insert({ id: 't2', text: 'buy bread', completed: false }));
16
+ const queryMap = new Map();
17
+ const { rerender, result, unmount } = renderHook((id) => {
18
+ renderCount.inc();
19
+ return LiveStoreReact.useTemporaryQuery(() => {
20
+ const query$ = querySQL(`select * from todos where id = '${id}'`, {
21
+ schema: Schema.Array(tables.todos.schema),
22
+ });
23
+ queryMap.set(id, query$);
24
+ return query$;
25
+ }, id);
26
+ }, { wrapper, initialProps: 't1' });
27
+ expect(result.current.length).toBe(1);
28
+ expect(result.current[0].text).toBe('buy milk');
29
+ expect(renderCount.val).toBe(1);
30
+ expect(queryMap.get('t1').runs).toBe(1);
31
+ rerender('t2');
32
+ expect(result.current.length).toBe(1);
33
+ expect(result.current[0].text).toBe('buy bread');
34
+ expect(renderCount.val).toBe(2);
35
+ expect(queryMap.get('t1').runs).toBe(1);
36
+ expect(queryMap.get('t2').runs).toBe(1);
37
+ unmount();
38
+ expect(queryMap.get('t2').runs).toBe(1);
39
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
40
+ // NOTE this test covers some special react lifecyle paths which I couldn't easily reproduce without react-window
41
+ // it basically causes a "query swap" in the `useMemo` and both a `useEffect` cleanup call.
42
+ // To handle this properly we introduced the `_tag: 'destroyed'` state in the `spanAlreadyStartedCache`.
43
+ it('should work for a list with react-window', () => Effect.gen(function* () {
44
+ const { wrapper } = yield* makeTodoMvcReact();
45
+ const ListWrapper = ({ numItems }) => {
46
+ return (React.createElement(ReactWindow.FixedSizeList, { height: 100, width: 100, itemSize: 10, itemCount: numItems, itemData: Array.from({ length: numItems }, (_, i) => i).reverse() }, ListItem));
47
+ };
48
+ const ListItem = ({ data: ids, index }) => {
49
+ const id = ids[index];
50
+ const res = LiveStoreReact.useTemporaryQuery(() => LiveStore.computed(() => id, { label: `ListItem.${id}` }), id);
51
+ return React.createElement("div", { role: "listitem" }, res);
52
+ };
53
+ const renderResult = render(React.createElement(ListWrapper, { numItems: 1 }), { wrapper });
54
+ expect(renderResult.container.textContent).toBe('0');
55
+ renderResult.rerender(React.createElement(ListWrapper, { numItems: 2 }));
56
+ expect(renderResult.container.textContent).toBe('10');
57
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
58
+ });
59
+ //# sourceMappingURL=useTemporaryQuery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemporaryQuery.test.js","sourceRoot":"","sources":["../src/useTemporaryQuery.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type StackInfo } from '@livestore/livestore';
2
+ export declare const originalStackLimit: number;
3
+ export declare const useStackInfo: () => StackInfo;
4
+ //# sourceMappingURL=stack-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-info.d.ts","sourceRoot":"","sources":["../../src/utils/stack-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAGrF,eAAO,MAAM,kBAAkB,QAAwB,CAAA;AAEvD,eAAO,MAAM,YAAY,QAAO,SAOxB,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { extractStackInfoFromStackTrace } from '@livestore/livestore';
2
+ import React from 'react';
3
+ export const originalStackLimit = Error.stackTraceLimit;
4
+ export const useStackInfo = () => React.useMemo(() => {
5
+ Error.stackTraceLimit = 10;
6
+ // eslint-disable-next-line unicorn/error-message
7
+ const stack = new Error().stack;
8
+ Error.stackTraceLimit = originalStackLimit;
9
+ return extractStackInfoFromStackTrace(stack);
10
+ }, []);
11
+ //# sourceMappingURL=stack-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-info.js","sourceRoot":"","sources":["../../src/utils/stack-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAkB,MAAM,sBAAsB,CAAA;AACrF,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,eAAe,CAAA;AAEvD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAc,EAAE,CAC1C,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;IACjB,KAAK,CAAC,eAAe,GAAG,EAAE,CAAA;IAC1B,iDAAiD;IACjD,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAM,CAAA;IAChC,KAAK,CAAC,eAAe,GAAG,kBAAkB,CAAA;IAC1C,OAAO,8BAA8B,CAAC,KAAK,CAAC,CAAA;AAC9C,CAAC,EAAE,EAAE,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ /**
3
+ * A variant of `React.useState` which allows the `inputState` to change over time as well.
4
+ * Important: This hook is synchronous / single-render-pass (i.e. doesn't use `useEffect` or `setState` directly).
5
+ *
6
+ * Notes:
7
+ * - The output state is always reset to the input state in case the input state changes (i.e. the previous "external" `setStateAndRerender` call is forgotten)
8
+ * - This hook might not work properly with React Suspense
9
+ * - Also see this Tweet for more potential problems: https://twitter.com/schickling/status/1677317711104278528
10
+ *
11
+ */
12
+ export declare const useStateRefWithReactiveInput: <T>(inputState: T) => [React.MutableRefObject<T>, (newState: T | ((prev: T) => T)) => void];
13
+ //# sourceMappingURL=useStateRefWithReactiveInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStateRefWithReactiveInput.d.ts","sourceRoot":"","sources":["../../src/utils/useStateRefWithReactiveInput.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,cAChC,CAAC,KACZ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAwBtE,CAAA"}
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ /**
3
+ * A variant of `React.useState` which allows the `inputState` to change over time as well.
4
+ * Important: This hook is synchronous / single-render-pass (i.e. doesn't use `useEffect` or `setState` directly).
5
+ *
6
+ * Notes:
7
+ * - The output state is always reset to the input state in case the input state changes (i.e. the previous "external" `setStateAndRerender` call is forgotten)
8
+ * - This hook might not work properly with React Suspense
9
+ * - Also see this Tweet for more potential problems: https://twitter.com/schickling/status/1677317711104278528
10
+ *
11
+ */
12
+ export const useStateRefWithReactiveInput = (inputState) => {
13
+ const [_, rerender] = React.useState(0);
14
+ const lastKnownInputStateRef = React.useRef(inputState);
15
+ const stateRef = React.useRef(inputState);
16
+ if (lastKnownInputStateRef.current !== inputState) {
17
+ lastKnownInputStateRef.current = inputState;
18
+ // NOTE we don't need to re-render here, because the component is already re-rendering due to the `inputState` change
19
+ stateRef.current = inputState;
20
+ }
21
+ const setStateAndRerender = React.useCallback((newState) => {
22
+ // @ts-expect-error https://github.com/microsoft/TypeScript/issues/37663
23
+ const val = typeof newState === 'function' ? newState(stateRef.current) : newState;
24
+ stateRef.current = val;
25
+ rerender((c) => c + 1);
26
+ }, [rerender]);
27
+ return [stateRef, setStateAndRerender];
28
+ };
29
+ // Down-side of this implementation: Double render pass due to `setState` call (which forces a re-render)
30
+ // Keeping around for now in case `useStateRefWithReactiveInput` doesn't work out
31
+ // const _useStateWithReactiveInput = <T>(inputState: T): [T, (newState: T | ((prev: T) => T)) => void] => {
32
+ // const [externalState, setExternalState] = React.useState(inputState)
33
+ // if (externalState !== inputState) {
34
+ // setExternalState(inputState)
35
+ // }
36
+ // return [externalState, setExternalState]
37
+ // }
38
+ //# sourceMappingURL=useStateRefWithReactiveInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStateRefWithReactiveInput.js","sourceRoot":"","sources":["../../src/utils/useStateRefWithReactiveInput.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAC1C,UAAa,EAC0D,EAAE;IACzE,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAEvC,MAAM,sBAAsB,GAAG,KAAK,CAAC,MAAM,CAAI,UAAU,CAAC,CAAA;IAC1D,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAI,UAAU,CAAC,CAAA;IAE5C,IAAI,sBAAsB,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QAClD,sBAAsB,CAAC,OAAO,GAAG,UAAU,CAAA;QAE3C,qHAAqH;QACrH,QAAQ,CAAC,OAAO,GAAG,UAAU,CAAA;IAC/B,CAAC;IAED,MAAM,mBAAmB,GAAG,KAAK,CAAC,WAAW,CAC3C,CAAC,QAA8B,EAAE,EAAE;QACjC,wEAAwE;QACxE,MAAM,GAAG,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;QAClF,QAAQ,CAAC,OAAO,GAAG,GAAG,CAAA;QACtB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACxB,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAA;IAED,OAAO,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAA;AACxC,CAAC,CAAA;AAED,yGAAyG;AACzG,iFAAiF;AACjF,4GAA4G;AAC5G,yEAAyE;AAEzE,wCAAwC;AACxC,mCAAmC;AACnC,MAAM;AAEN,6CAA6C;AAC7C,IAAI"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@livestore/react",
3
+ "version": "0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/mod.d.ts",
8
+ "default": "./dist/mod.js"
9
+ },
10
+ "./experimental": {
11
+ "types": "./dist/experimental/mod.d.ts",
12
+ "default": "./dist/experimental/mod.js"
13
+ }
14
+ },
15
+ "types": "./dist/mod.d.ts",
16
+ "typesVersions": {
17
+ "*": {
18
+ "./experimental": [
19
+ "./dist/experimental/mod.d.ts"
20
+ ]
21
+ }
22
+ },
23
+ "dependencies": {
24
+ "@opentelemetry/api": "^1.9.0",
25
+ "@livestore/common": "0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df",
26
+ "@livestore/utils": "0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df",
27
+ "@livestore/livestore": "0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df",
28
+ "@livestore/db-schema": "0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df"
29
+ },
30
+ "devDependencies": {
31
+ "@opentelemetry/sdk-trace-base": "1.27.0",
32
+ "@testing-library/react": "^16.0.1",
33
+ "@types/react": "^18.3.12",
34
+ "@types/react-dom": "^18.3.1",
35
+ "jsdom": "^25.0.1",
36
+ "react": "^18.3.1",
37
+ "react-dom": "^18.3.1",
38
+ "react-window": "^1.8.10",
39
+ "typescript": "5.6.3",
40
+ "vite": "5.4.10",
41
+ "vitest": "^2.1.4",
42
+ "@livestore/web": "0.0.0-snapshot-8d3edf87cb1e88c7b67c5f3ea9d0b307253c33df"
43
+ },
44
+ "peerDependencies": {
45
+ "react": "^18"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc",
52
+ "test": "vitest && REACT_STRICT_MODE=1 vitest"
53
+ }
54
+ }
@@ -0,0 +1,19 @@
1
+ import type { Store } from '@livestore/livestore'
2
+ import type { LiveStoreContextRunning as LiveStoreContext_ } from '@livestore/livestore/effect'
3
+ import React, { useContext } from 'react'
4
+
5
+ export const LiveStoreContext = React.createContext<LiveStoreContext_ | undefined>(undefined)
6
+
7
+ export const useStore = (): { store: Store } => {
8
+ const storeContext = useContext(LiveStoreContext)
9
+
10
+ if (storeContext === undefined) {
11
+ throw new Error(`useStore can only be used inside StoreContext.Provider`)
12
+ }
13
+
14
+ if (storeContext.stage !== 'running') {
15
+ throw new Error(`useStore can only be used after the store is running`)
16
+ }
17
+
18
+ return storeContext
19
+ }