@livestore/livestore 0.0.56-dev.2 → 0.0.56-dev.3
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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/SynchronousDatabaseWrapper.d.ts.map +1 -1
- package/dist/SynchronousDatabaseWrapper.js +9 -18
- package/dist/SynchronousDatabaseWrapper.js.map +1 -1
- package/dist/__tests__/react/fixture.d.ts +3 -4
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +7 -5
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +4 -24
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +2 -1
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreContext.d.ts +1 -2
- package/dist/react/LiveStoreContext.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.d.ts +5 -13
- package/dist/react/LiveStoreProvider.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.js +25 -12
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.js +1 -1
- package/dist/react/LiveStoreProvider.test.js.map +1 -1
- package/dist/react/useQuery.test.js +7 -7
- package/dist/react/useQuery.test.js.map +1 -1
- package/dist/react/useRow.test.js +52 -46
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useTemporaryQuery.test.js +4 -4
- package/dist/react/useTemporaryQuery.test.js.map +1 -1
- package/dist/reactiveQueries/sql.test.js +34 -33
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/store-context.d.ts +26 -0
- package/dist/store-context.d.ts.map +1 -0
- package/dist/store-context.js +6 -0
- package/dist/store-context.js.map +1 -0
- package/dist/store-devtools.d.ts +1 -1
- package/dist/store-devtools.d.ts.map +1 -1
- package/dist/store-devtools.js +5 -0
- package/dist/store-devtools.js.map +1 -1
- package/dist/store.d.ts +8 -23
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +30 -35
- package/dist/store.js.map +1 -1
- package/package.json +5 -5
- package/src/SynchronousDatabaseWrapper.ts +10 -18
- package/src/__tests__/react/fixture.tsx +53 -50
- package/src/effect/LiveStore.ts +5 -34
- package/src/index.ts +2 -10
- package/src/react/LiveStoreProvider.test.tsx +1 -1
- package/src/react/LiveStoreProvider.tsx +37 -19
- package/src/react/useQuery.test.tsx +53 -51
- package/src/react/useRow.test.tsx +237 -224
- package/src/react/useTemporaryQuery.test.tsx +46 -45
- package/src/reactiveQueries/sql.test.ts +36 -33
- package/src/store-context.ts +23 -0
- package/src/store-devtools.ts +8 -0
- package/src/store.ts +55 -59
- package/vitest.config.js +1 -1
package/src/effect/LiveStore.ts
CHANGED
|
@@ -5,40 +5,12 @@ import { Context, Deferred, Duration, Effect, FiberSet, Layer, OtelTracer, pipe
|
|
|
5
5
|
import * as otel from '@opentelemetry/api'
|
|
6
6
|
import type { GraphQLSchema } from 'graphql'
|
|
7
7
|
|
|
8
|
-
import type {
|
|
9
|
-
import type { BaseGraphQLContext, GraphQLOptions, OtelOptions, Store } from '../store.js'
|
|
8
|
+
import type { BaseGraphQLContext } from '../store.js'
|
|
10
9
|
import { createStore } from '../store.js'
|
|
10
|
+
import type { LiveStoreContextRunning as LiveStoreContextRunning_ } from '../store-context.js'
|
|
11
11
|
import type { SynchronousDatabaseWrapper } from '../SynchronousDatabaseWrapper.js'
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
export type LiveStoreContext =
|
|
15
|
-
| LiveStoreContextRunning
|
|
16
|
-
| {
|
|
17
|
-
stage: 'error'
|
|
18
|
-
error: UnexpectedError | unknown
|
|
19
|
-
}
|
|
20
|
-
| {
|
|
21
|
-
stage: 'shutdown'
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type LiveStoreContextRunning = {
|
|
25
|
-
stage: 'running'
|
|
26
|
-
store: Store
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export type QueryDefinition = <TResult>(store: Store) => LiveQuery<TResult>
|
|
30
|
-
|
|
31
|
-
export type LiveStoreCreateStoreOptions<GraphQLContext extends BaseGraphQLContext> = {
|
|
32
|
-
schema: LiveStoreSchema
|
|
33
|
-
graphQLOptions?: GraphQLOptions<GraphQLContext>
|
|
34
|
-
otelOptions?: OtelOptions
|
|
35
|
-
boot?: (db: BootDb, parentSpan: otel.Span) => void | Promise<void> | Effect.Effect<void, unknown, otel.Tracer>
|
|
36
|
-
adapter: StoreAdapterFactory
|
|
37
|
-
batchUpdates?: (run: () => void) => void
|
|
38
|
-
disableDevtools?: boolean
|
|
39
|
-
signal?: AbortSignal
|
|
40
|
-
}
|
|
41
|
-
|
|
13
|
+
export type LiveStoreContextRunning = LiveStoreContextRunning_
|
|
42
14
|
export const LiveStoreContextRunning = Context.GenericTag<LiveStoreContextRunning>(
|
|
43
15
|
'@livestore/livestore/effect/LiveStoreContextRunning',
|
|
44
16
|
)
|
|
@@ -48,8 +20,6 @@ export const DeferredStoreContext = Context.GenericTag<DeferredStoreContext>(
|
|
|
48
20
|
'@livestore/livestore/effect/DeferredStoreContext',
|
|
49
21
|
)
|
|
50
22
|
|
|
51
|
-
// export const DeferredStoreContext = Effect.cached(Effect.flatMap(StoreContext, (_) => Effect.succeed(_)))
|
|
52
|
-
|
|
53
23
|
export type LiveStoreContextProps<GraphQLContext extends BaseGraphQLContext> = {
|
|
54
24
|
schema: LiveStoreSchema
|
|
55
25
|
graphQLOptions?: {
|
|
@@ -114,7 +84,8 @@ export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>(
|
|
|
114
84
|
onBootStatus,
|
|
115
85
|
})
|
|
116
86
|
|
|
117
|
-
window.__debugLiveStore
|
|
87
|
+
window.__debugLiveStore ??= {}
|
|
88
|
+
window.__debugLiveStore[schema.key] = store
|
|
118
89
|
|
|
119
90
|
return { stage: 'running', store } satisfies LiveStoreContextRunning
|
|
120
91
|
}),
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
export { Store, createStorePromise, createStore } from './store.js'
|
|
2
2
|
export type { BaseGraphQLContext, QueryDebugInfo, RefreshReason } from './store.js'
|
|
3
3
|
|
|
4
|
-
export type {
|
|
5
|
-
QueryDefinition,
|
|
6
|
-
LiveStoreCreateStoreOptions,
|
|
7
|
-
LiveStoreContextRunning as LiveStoreContext,
|
|
8
|
-
} from './effect/LiveStore.js'
|
|
4
|
+
export type { LiveStoreContextRunning as LiveStoreContext } from './effect/LiveStore.js'
|
|
9
5
|
|
|
10
6
|
export { SynchronousDatabaseWrapper, emptyDebugInfo } from './SynchronousDatabaseWrapper.js'
|
|
11
7
|
|
|
@@ -52,8 +48,4 @@ export { SqliteAst, SqliteDsl } from 'effect-db-schema'
|
|
|
52
48
|
|
|
53
49
|
export { deepEqual } from '@livestore/utils'
|
|
54
50
|
|
|
55
|
-
export type {
|
|
56
|
-
StoreAdapter as DatabaseImpl,
|
|
57
|
-
StoreAdapterFactory as DatabaseFactory,
|
|
58
|
-
PreparedStatement,
|
|
59
|
-
} from '@livestore/common'
|
|
51
|
+
export type { StoreAdapter, StoreAdapterFactory, PreparedStatement } from '@livestore/common'
|
|
@@ -65,7 +65,7 @@ describe('LiveStoreProvider', () => {
|
|
|
65
65
|
|
|
66
66
|
abortController.abort()
|
|
67
67
|
|
|
68
|
-
await waitFor(() => screen.getByText('LiveStore Shutdown'))
|
|
68
|
+
await waitFor(() => screen.getByText('LiveStore Shutdown due to abort signal'))
|
|
69
69
|
})
|
|
70
70
|
|
|
71
71
|
it('error during boot', async () => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BootDb, BootStatus, IntentionalShutdownCause, StoreAdapterFactory } from '@livestore/common'
|
|
2
|
+
import { UnexpectedError } from '@livestore/common'
|
|
2
3
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
3
4
|
import { errorToString } from '@livestore/utils'
|
|
4
5
|
import { Effect, FiberSet, Logger, LogLevel, Schema } from '@livestore/utils/effect'
|
|
@@ -6,15 +7,12 @@ import type * as otel from '@opentelemetry/api'
|
|
|
6
7
|
import type { ReactElement, ReactNode } from 'react'
|
|
7
8
|
import React from 'react'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
import type { LiveStoreContext as StoreContext_, LiveStoreCreateStoreOptions } from '../effect/LiveStore.js'
|
|
11
|
-
import type { BaseGraphQLContext, ForceStoreShutdown, GraphQLOptions, OtelOptions, StoreShutdown } from '../store.js'
|
|
10
|
+
import type { BaseGraphQLContext, CreateStoreOptions, GraphQLOptions, OtelOptions } from '../store.js'
|
|
12
11
|
import { createStore } from '../store.js'
|
|
12
|
+
import type { LiveStoreContext as StoreContext_ } from '../store-context.js'
|
|
13
|
+
import { StoreAbort, StoreInterrupted } from '../store-context.js'
|
|
13
14
|
import { LiveStoreContext } from './LiveStoreContext.js'
|
|
14
15
|
|
|
15
|
-
export class StoreAbort extends Schema.TaggedError<StoreAbort>()('LiveStore.StoreAbort', {}) {}
|
|
16
|
-
export class StoreInterrupted extends Schema.TaggedError<StoreInterrupted>()('LiveStore.StoreInterrupted', {}) {}
|
|
17
|
-
|
|
18
16
|
interface LiveStoreProviderProps<GraphQLContext> {
|
|
19
17
|
schema: LiveStoreSchema
|
|
20
18
|
boot?: (db: BootDb, parentSpan: otel.Span) => void | Promise<void> | Effect.Effect<void, unknown, otel.Tracer>
|
|
@@ -22,7 +20,7 @@ interface LiveStoreProviderProps<GraphQLContext> {
|
|
|
22
20
|
otelOptions?: OtelOptions
|
|
23
21
|
renderLoading: (status: BootStatus) => ReactElement
|
|
24
22
|
renderError?: (error: UnexpectedError | unknown) => ReactElement
|
|
25
|
-
renderShutdown?: () => ReactElement
|
|
23
|
+
renderShutdown?: (cause: IntentionalShutdownCause | StoreAbort) => ReactElement
|
|
26
24
|
adapter: StoreAdapterFactory
|
|
27
25
|
batchUpdates?: (run: () => void) => void
|
|
28
26
|
disableDevtools?: boolean
|
|
@@ -32,7 +30,18 @@ interface LiveStoreProviderProps<GraphQLContext> {
|
|
|
32
30
|
const defaultRenderError = (error: UnexpectedError | unknown) => (
|
|
33
31
|
<>{Schema.is(UnexpectedError)(error) ? error.toString() : errorToString(error)}</>
|
|
34
32
|
)
|
|
35
|
-
const defaultRenderShutdown = () =>
|
|
33
|
+
const defaultRenderShutdown = (cause: IntentionalShutdownCause | StoreAbort) => {
|
|
34
|
+
const reason =
|
|
35
|
+
cause._tag === 'LiveStore.StoreAbort'
|
|
36
|
+
? 'abort signal'
|
|
37
|
+
: cause.reason === 'devtools-import'
|
|
38
|
+
? 'devtools import'
|
|
39
|
+
: cause.reason === 'devtools-reset'
|
|
40
|
+
? 'devtools reset'
|
|
41
|
+
: 'unknown reason'
|
|
42
|
+
|
|
43
|
+
return <>LiveStore Shutdown due to {reason}</>
|
|
44
|
+
}
|
|
36
45
|
|
|
37
46
|
export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
38
47
|
renderLoading,
|
|
@@ -64,14 +73,15 @@ export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
if (storeCtx.stage === 'shutdown') {
|
|
67
|
-
return renderShutdown()
|
|
76
|
+
return renderShutdown(storeCtx.cause)
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
if (storeCtx.stage !== 'running') {
|
|
71
80
|
return renderLoading(storeCtx)
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
window.__debugLiveStore
|
|
83
|
+
window.__debugLiveStore ??= {}
|
|
84
|
+
window.__debugLiveStore[schema.key] = storeCtx.store
|
|
75
85
|
|
|
76
86
|
return <LiveStoreContext.Provider value={storeCtx}>{children}</LiveStoreContext.Provider>
|
|
77
87
|
}
|
|
@@ -96,8 +106,9 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
96
106
|
adapter,
|
|
97
107
|
batchUpdates,
|
|
98
108
|
disableDevtools,
|
|
109
|
+
reactivityGraph,
|
|
99
110
|
signal,
|
|
100
|
-
}:
|
|
111
|
+
}: CreateStoreOptions<GraphQLContext, LiveStoreSchema> & { signal?: AbortSignal }) => {
|
|
101
112
|
const [_, rerender] = React.useState(0)
|
|
102
113
|
const ctxValueRef = React.useRef<{
|
|
103
114
|
value: StoreContext_ | BootStatus
|
|
@@ -119,6 +130,7 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
119
130
|
adapter,
|
|
120
131
|
batchUpdates,
|
|
121
132
|
disableDevtools,
|
|
133
|
+
reactivityGraph,
|
|
122
134
|
signal,
|
|
123
135
|
})
|
|
124
136
|
|
|
@@ -126,7 +138,10 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
126
138
|
Effect.gen(function* () {
|
|
127
139
|
yield* FiberSet.clear(fiberSet)
|
|
128
140
|
yield* FiberSet.run(fiberSet, Effect.fail(error))
|
|
129
|
-
}).pipe(
|
|
141
|
+
}).pipe(
|
|
142
|
+
Effect.tapErrorCause((cause) => Effect.logDebug(`[@livestore/livestore/react] interupting`, cause)),
|
|
143
|
+
Effect.runFork,
|
|
144
|
+
)
|
|
130
145
|
|
|
131
146
|
if (
|
|
132
147
|
inputPropsCacheRef.current.schema !== schema ||
|
|
@@ -136,6 +151,7 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
136
151
|
inputPropsCacheRef.current.adapter !== adapter ||
|
|
137
152
|
inputPropsCacheRef.current.batchUpdates !== batchUpdates ||
|
|
138
153
|
inputPropsCacheRef.current.disableDevtools !== disableDevtools ||
|
|
154
|
+
inputPropsCacheRef.current.reactivityGraph !== reactivityGraph ||
|
|
139
155
|
inputPropsCacheRef.current.signal !== signal
|
|
140
156
|
) {
|
|
141
157
|
inputPropsCacheRef.current = {
|
|
@@ -146,6 +162,7 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
146
162
|
adapter,
|
|
147
163
|
batchUpdates,
|
|
148
164
|
disableDevtools,
|
|
165
|
+
reactivityGraph,
|
|
149
166
|
signal,
|
|
150
167
|
}
|
|
151
168
|
if (ctxValueRef.current.fiberSet !== undefined) {
|
|
@@ -174,7 +191,7 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
174
191
|
Effect.gen(function* () {
|
|
175
192
|
const fiberSet = yield* FiberSet.make<
|
|
176
193
|
unknown,
|
|
177
|
-
UnexpectedError |
|
|
194
|
+
UnexpectedError | IntentionalShutdownCause | StoreAbort | StoreInterrupted
|
|
178
195
|
>()
|
|
179
196
|
|
|
180
197
|
ctxValueRef.current.fiberSet = fiberSet
|
|
@@ -187,6 +204,7 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
187
204
|
otelOptions,
|
|
188
205
|
boot,
|
|
189
206
|
adapter,
|
|
207
|
+
reactivityGraph,
|
|
190
208
|
batchUpdates,
|
|
191
209
|
disableDevtools,
|
|
192
210
|
onBootStatus: (status) => {
|
|
@@ -200,12 +218,12 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
200
218
|
yield* Effect.never
|
|
201
219
|
}).pipe(Effect.scoped, FiberSet.run(fiberSet))
|
|
202
220
|
|
|
203
|
-
const shutdownContext =
|
|
221
|
+
const shutdownContext = (cause: IntentionalShutdownCause | StoreAbort) =>
|
|
222
|
+
Effect.sync(() => setContextValue({ stage: 'shutdown', cause }))
|
|
204
223
|
|
|
205
224
|
yield* FiberSet.join(fiberSet).pipe(
|
|
206
|
-
Effect.catchTag('LiveStore.
|
|
207
|
-
Effect.catchTag('LiveStore.
|
|
208
|
-
Effect.catchTag('LiveStore.StoreAbort', () => shutdownContext),
|
|
225
|
+
Effect.catchTag('LiveStore.IntentionalShutdownCause', (cause) => shutdownContext(cause)),
|
|
226
|
+
Effect.catchTag('LiveStore.StoreAbort', (cause) => shutdownContext(cause)),
|
|
209
227
|
Effect.tapError((error) => Effect.sync(() => setContextValue({ stage: 'error', error }))),
|
|
210
228
|
Effect.tapDefect((defect) => Effect.sync(() => setContextValue({ stage: 'error', error: defect }))),
|
|
211
229
|
Effect.exit,
|
|
@@ -229,7 +247,7 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
229
247
|
ctxValueRef.current.fiberSet = undefined
|
|
230
248
|
}
|
|
231
249
|
}
|
|
232
|
-
}, [schema, graphQLOptions, otelOptions, boot, adapter, batchUpdates, disableDevtools, signal])
|
|
250
|
+
}, [schema, graphQLOptions, otelOptions, boot, adapter, batchUpdates, disableDevtools, signal, reactivityGraph])
|
|
233
251
|
|
|
234
252
|
return ctxValueRef.current.value
|
|
235
253
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema } from '@livestore/utils/effect'
|
|
1
|
+
import { Effect, Schema } from '@livestore/utils/effect'
|
|
2
2
|
import { renderHook } from '@testing-library/react'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { describe, expect, it } from 'vitest'
|
|
@@ -8,73 +8,75 @@ import { querySQL } from '../reactiveQueries/sql.js'
|
|
|
8
8
|
import * as LiveStoreReact from './index.js'
|
|
9
9
|
|
|
10
10
|
describe('useQuery', () => {
|
|
11
|
-
it('simple',
|
|
12
|
-
|
|
11
|
+
it('simple', () =>
|
|
12
|
+
Effect.gen(function* () {
|
|
13
|
+
const { wrapper, store, makeRenderCount } = yield* makeTodoMvc()
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
const renderCount = makeRenderCount()
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
const allTodos$ = querySQL(`select * from todos`, { schema: Schema.Array(tables.todos.schema) })
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const { result } = renderHook(
|
|
20
|
+
() => {
|
|
21
|
+
renderCount.inc()
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
return LiveStoreReact.useQuery(allTodos$)
|
|
24
|
+
},
|
|
25
|
+
{ wrapper },
|
|
26
|
+
)
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
expect(result.current.length).toBe(0)
|
|
29
|
+
expect(renderCount.val).toBe(1)
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
React.act(() => store.mutate(todos.insert({ id: 't1', text: 'buy milk', completed: false })))
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
expect(result.current.length).toBe(1)
|
|
34
|
+
expect(result.current[0]!.text).toBe('buy milk')
|
|
35
|
+
expect(renderCount.val).toBe(2)
|
|
36
|
+
}).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise))
|
|
36
37
|
|
|
37
|
-
it('same `useQuery` hook invoked with different queries',
|
|
38
|
-
|
|
38
|
+
it('same `useQuery` hook invoked with different queries', () =>
|
|
39
|
+
Effect.gen(function* () {
|
|
40
|
+
const { wrapper, store, makeRenderCount } = yield* makeTodoMvc()
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
const renderCount = makeRenderCount()
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const todo1$ = querySQL(`select * from todos where id = 't1'`, {
|
|
45
|
+
label: 'libraryTracksView1',
|
|
46
|
+
schema: Schema.Array(tables.todos.schema),
|
|
47
|
+
})
|
|
48
|
+
const todo2$ = querySQL(`select * from todos where id = 't2'`, {
|
|
49
|
+
label: 'libraryTracksView2',
|
|
50
|
+
schema: Schema.Array(tables.todos.schema),
|
|
51
|
+
})
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
store.mutate(
|
|
54
|
+
todos.insert({ id: 't1', text: 'buy milk', completed: false }),
|
|
55
|
+
todos.insert({ id: 't2', text: 'buy eggs', completed: false }),
|
|
56
|
+
)
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
const { result, rerender } = renderHook(
|
|
59
|
+
(todoId: string) => {
|
|
60
|
+
renderCount.inc()
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
const query$ = React.useMemo(() => (todoId === 't1' ? todo1$ : todo2$), [todoId])
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
return LiveStoreReact.useQuery(query$)[0]!.text
|
|
65
|
+
},
|
|
66
|
+
{ wrapper, initialProps: 't1' },
|
|
67
|
+
)
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
expect(result.current).toBe('buy milk')
|
|
70
|
+
expect(renderCount.val).toBe(1)
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
React.act(() => store.mutate(todos.update({ where: { id: 't1' }, values: { text: 'buy soy milk' } })))
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
expect(result.current).toBe('buy soy milk')
|
|
75
|
+
expect(renderCount.val).toBe(2)
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
rerender('t2')
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
expect(result.current).toBe('buy eggs')
|
|
80
|
+
expect(renderCount.val).toBe(3)
|
|
81
|
+
}).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise))
|
|
80
82
|
})
|