@livestore/react 0.3.0-dev.4 → 0.3.0-dev.6

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.
@@ -10,6 +10,8 @@ import { describe, expect, it } from 'vitest'
10
10
  import { AppComponentSchema, AppRouterSchema, makeTodoMvcReact, tables, todos } from './__tests__/fixture.js'
11
11
  import * as LiveStoreReact from './mod.js'
12
12
 
13
+ // const strictMode = process.env.REACT_STRICT_MODE !== undefined
14
+
13
15
  // NOTE running tests concurrently doesn't work with the default global db graph
14
16
  describe('useRow', () => {
15
17
  it('should update the data based on component key', () =>
@@ -257,87 +259,86 @@ describe('useRow', () => {
257
259
  unmount()
258
260
  }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise))
259
261
 
260
- let cachedProvider: BasicTracerProvider | undefined
261
-
262
262
  describe('otel', () => {
263
- const exporter = new InMemorySpanExporter()
264
-
265
- const provider = cachedProvider ?? new BasicTracerProvider({ spanProcessors: [new SimpleSpanProcessor(exporter)] })
266
- cachedProvider = provider
263
+ const provider = new BasicTracerProvider({})
267
264
  provider.register()
268
265
 
269
- const otelTracer = otel.trace.getTracer('test')
266
+ it.each([{ strictMode: true }, { strictMode: false }])(
267
+ 'should update the data based on component key strictMode=%s',
268
+ async ({ strictMode }) => {
269
+ const exporter = new InMemorySpanExporter()
270
270
 
271
- const span = otelTracer.startSpan('test-root')
272
- const otelContext = otel.trace.setSpan(otel.context.active(), span)
271
+ // const provider = cachedProvider ?? new BasicTracerProvider({ spanProcessors: [new SimpleSpanProcessor(exporter)] })
272
+ provider.addSpanProcessor(new SimpleSpanProcessor(exporter))
273
273
 
274
- it('should update the data based on component key', async () => {
275
- const { strictMode } = await Effect.gen(function* () {
276
- const { wrapper, store, reactivityGraph, makeRenderCount, strictMode } = yield* makeTodoMvcReact({
277
- useGlobalReactivityGraph: false,
278
- otelContext,
279
- otelTracer,
280
- })
274
+ const otelTracer = otel.trace.getTracer(`testing-${strictMode ? 'strict' : 'non-strict'}`)
281
275
 
282
- const renderCount = makeRenderCount()
276
+ const span = otelTracer.startSpan('test-root')
277
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
283
278
 
284
- const { result, rerender, unmount } = renderHook(
285
- (userId: string) => {
286
- renderCount.inc()
279
+ await Effect.gen(function* () {
280
+ const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
281
+ useGlobalReactivityGraph: false,
282
+ otelContext,
283
+ otelTracer,
284
+ strictMode,
285
+ })
287
286
 
288
- const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph })
289
- return { state, setState }
290
- },
291
- { wrapper, initialProps: 'u1' },
292
- )
287
+ const renderCount = makeRenderCount()
293
288
 
294
- expect(result.current.state.id).toBe('u1')
295
- expect(result.current.state.username).toBe('')
296
- expect(renderCount.val).toBe(1)
289
+ const { result, rerender, unmount } = renderHook(
290
+ (userId: string) => {
291
+ renderCount.inc()
297
292
 
298
- React.act(() =>
299
- store.mutate(
300
- LiveStore.rawSqlMutation({
301
- sql: LiveStore.sql`INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
302
- }),
303
- ),
304
- )
293
+ const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph })
294
+ return { state, setState }
295
+ },
296
+ { wrapper, initialProps: 'u1' },
297
+ )
305
298
 
306
- rerender('u2')
307
-
308
- expect(result.current.state.id).toBe('u2')
309
- expect(result.current.state.username).toBe('username_u2')
310
- expect(renderCount.val).toBe(2)
311
-
312
- unmount()
313
- span.end()
314
-
315
- return { strictMode }
316
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise)
317
-
318
- const mapAttributes = (attributes: otel.Attributes) => {
319
- return ReadonlyRecord.map(attributes, (val, key) => {
320
- if (key === 'stackInfo') {
321
- const stackInfo = JSON.parse(val as string) as LiveStore.StackInfo
322
- // stackInfo.frames.shift() // Removes `renderHook.wrapper` from the stack
323
- stackInfo.frames.forEach((_) => {
324
- if (_.name.includes('renderHook.wrapper')) {
325
- _.name = 'renderHook.wrapper'
326
- }
327
- _.filePath = '__REPLACED_FOR_SNAPSHOT__'
328
- })
329
- return JSON.stringify(stackInfo)
330
- }
331
- return val
332
- })
333
- }
299
+ expect(result.current.state.id).toBe('u1')
300
+ expect(result.current.state.username).toBe('')
301
+ expect(renderCount.val).toBe(1)
334
302
 
335
- // TODO improve testing setup so "obsolete" warning is avoided
336
- if (strictMode) {
337
- expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot('strictMode=true')
338
- } else {
339
- expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot('strictMode=false')
340
- }
341
- })
303
+ React.act(() =>
304
+ store.mutate(
305
+ LiveStore.rawSqlMutation({
306
+ sql: LiveStore.sql`INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
307
+ }),
308
+ ),
309
+ )
310
+
311
+ rerender('u2')
312
+
313
+ expect(result.current.state.id).toBe('u2')
314
+ expect(result.current.state.username).toBe('username_u2')
315
+ expect(renderCount.val).toBe(2)
316
+
317
+ unmount()
318
+ span.end()
319
+
320
+ return { strictMode }
321
+ }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise)
322
+
323
+ const mapAttributes = (attributes: otel.Attributes) => {
324
+ return ReadonlyRecord.map(attributes, (val, key) => {
325
+ if (key === 'stackInfo') {
326
+ const stackInfo = JSON.parse(val as string) as LiveStore.StackInfo
327
+ // stackInfo.frames.shift() // Removes `renderHook.wrapper` from the stack
328
+ stackInfo.frames.forEach((_) => {
329
+ if (_.name.includes('renderHook.wrapper')) {
330
+ _.name = 'renderHook.wrapper'
331
+ }
332
+ _.filePath = '__REPLACED_FOR_SNAPSHOT__'
333
+ })
334
+ return JSON.stringify(stackInfo)
335
+ }
336
+ return val
337
+ })
338
+ }
339
+
340
+ expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
341
+ },
342
+ )
342
343
  })
343
344
  })
package/src/useRow.ts CHANGED
@@ -120,7 +120,7 @@ export const useRow: {
120
120
  },
121
121
  )
122
122
 
123
- const query$Ref = useQueryRef(query$, otelContext) as React.MutableRefObject<RowQuery.Result<TTableDef>>
123
+ const query$Ref = useQueryRef(query$, otelContext) as React.RefObject<RowQuery.Result<TTableDef>>
124
124
 
125
125
  const setState = React.useMemo<StateSetters<TTableDef>>(() => {
126
126
  if (table.options.isSingleColumn) {
@@ -48,7 +48,7 @@ export const useScopedQuery = <TResult>(makeQuery: () => LiveQuery<TResult>, key
48
48
  export const useScopedQueryRef = <TResult>(
49
49
  makeQuery: () => LiveQuery<TResult>,
50
50
  key: DepKey,
51
- ): React.MutableRefObject<TResult> => {
51
+ ): React.RefObject<TResult> => {
52
52
  const { query$ } = useMakeScopedQuery(makeQuery, key)
53
53
 
54
54
  return useQueryRef(query$)
@@ -71,7 +71,7 @@ export const useMakeScopedQuery = <TResult, TQueryInfo extends QueryInfo>(
71
71
  () => (Array.isArray(key) ? key.join('-') : key) + '-' + store.reactivityGraph.id + '-' + makeQuery.toString(),
72
72
  [key, makeQuery, store.reactivityGraph.id],
73
73
  )
74
- const fullKeyRef = React.useRef<string>()
74
+ const fullKeyRef = React.useRef<string | undefined>(undefined)
75
75
 
76
76
  const { query$, otelContext } = React.useMemo(() => {
77
77
  if (fullKeyRef.current !== undefined && fullKeyRef.current !== fullKey) {
@@ -107,6 +107,7 @@ export const useMakeScopedQuery = <TResult, TQueryInfo extends QueryInfo>(
107
107
  )
108
108
 
109
109
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
110
+ // console.debug('useScopedQuery:startSpan', fullKey, spanName)
110
111
 
111
112
  const query$ = makeQuery(otelContext)
112
113
 
@@ -12,7 +12,7 @@ import React from 'react'
12
12
  */
13
13
  export const useStateRefWithReactiveInput = <T>(
14
14
  inputState: T,
15
- ): [React.MutableRefObject<T>, (newState: T | ((prev: T) => T)) => void] => {
15
+ ): [React.RefObject<T>, (newState: T | ((prev: T) => T)) => void] => {
16
16
  const [_, rerender] = React.useState(0)
17
17
 
18
18
  const lastKnownInputStateRef = React.useRef<T>(inputState)