Skip to content

Commit 22e5866

Browse files
authored
Update to React 19 (#321)
* Upgrade to react 19 * Change waitFor timeout and remove uneeded waitFor usage. Upgrade use-sync-external-store * sync cpackage-lock.json * Add removed types again
1 parent 34ceb93 commit 22e5866

8 files changed

+5808
-6190
lines changed

package-lock.json

Lines changed: 5724 additions & 6131 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,27 @@
4141
"trailingComma": "all"
4242
},
4343
"devDependencies": {
44-
"@babel/preset-env": "^7.22.7",
45-
"@babel/preset-typescript": "^7.22.5",
46-
"@testing-library/react": "^14.0.0",
47-
"@types/node": "^20.4.7",
48-
"@types/react": "^18.2.14",
49-
"@types/react-dom": "^18.2.6",
50-
"@vitest/coverage-v8": "^0.33.0",
51-
"esbuild": "^0.18.11",
44+
"@babel/preset-env": "^7.26.0",
45+
"@babel/preset-typescript": "^7.26.0",
46+
"@testing-library/react": "^16.1.0",
47+
"@types/node": "^22.10.5",
48+
"@types/react": "^19.0.4",
49+
"@types/react-dom": "^19.0.2",
50+
"@vitest/coverage-v8": "^2.1.8",
51+
"esbuild": "^0.24.2",
5252
"expose-gc": "^1.0.0",
5353
"husky": ">=8.0.3",
54-
"jest-environment-jsdom": "^29.6.1",
55-
"jsdom": "^22.1.0",
56-
"lint-staged": ">=13.2.3",
57-
"prettier": "^3.0.0",
58-
"react": "^18.2.0",
59-
"react-dom": "^18.2.0",
60-
"react-test-renderer": "^18.2.0",
54+
"jest-environment-jsdom": "^29.7.0",
55+
"jsdom": "^26.0.0",
56+
"lint-staged": "^15.3.0",
57+
"prettier": "^3.4.2",
58+
"react": "^19.0.0",
59+
"react-dom": "^19.0.0",
60+
"react-test-renderer": "^19.0.0",
6161
"rxjs": "^7.8.1",
62-
"tslib": "^2.6.0",
63-
"typescript": "^5.1.6",
64-
"vitest": "^0.33.0"
62+
"tslib": "^2.8.1",
63+
"typescript": "^5.7.3",
64+
"vitest": "^2.1.8"
6565
},
6666
"lint-staged": {
6767
"*.{js,jsx,ts,tsx,json,md}": "prettier --write"

packages/core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
],
5454
"dependencies": {
5555
"@rx-state/core": "0.1.4",
56-
"use-sync-external-store": "^1.0.0"
56+
"use-sync-external-store": "^1.4.0"
5757
},
5858
"devDependencies": {
59-
"@types/use-sync-external-store": "^0.0.3"
59+
"@types/use-sync-external-store": "^0.0.6"
6060
}
6161
}

packages/core/src/Subscribe.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,13 @@ export const Subscribe: React.FC<{
4545
source$?: Observable<any>
4646
fallback?: NonNullable<ReactNode> | null
4747
}> = ({ source$, children, fallback }) => {
48-
const subscriptionRef = useRef<{
49-
s: Subscription
50-
u: (source: StateObservable<any>) => void
51-
}>()
48+
const subscriptionRef = useRef<
49+
| {
50+
s: Subscription
51+
u: (source: StateObservable<any>) => void
52+
}
53+
| undefined
54+
>(undefined)
5255

5356
if (!subscriptionRef.current) {
5457
const s = new Subscription()

packages/core/src/bind/connectFactoryObservable.test.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,13 @@ describe("connectFactoryObservable", () => {
8989

9090
await wait(110)
9191

92-
expect(screen.queryByText("Result 1")).not.toBeNull()
93-
expect(screen.queryByText("Waiting")).toBeNull()
92+
vi.waitFor(
93+
() => {
94+
expect(screen.queryByText("Result 1")).not.toBeNull()
95+
expect(screen.queryByText("Waiting")).toBeNull()
96+
},
97+
{ timeout: 2000 },
98+
)
9499
})
95100

96101
it("synchronously mounts the emitted value if the observable emits synchronously", () => {
@@ -311,7 +316,7 @@ describe("connectFactoryObservable", () => {
311316
})
312317

313318
it("allows errors to be caught in error boundaries", () => {
314-
const errStream = new Subject()
319+
const errStream = new Subject<any>()
315320
const [useError] = bind(() => errStream, 1)
316321

317322
const ErrorComponent = () => {
@@ -338,7 +343,7 @@ describe("connectFactoryObservable", () => {
338343
})
339344

340345
it("allows sync errors to be caught in error boundaries with suspense", () => {
341-
const errStream = new Observable((observer) =>
346+
const errStream = new Observable<any>((observer) =>
342347
observer.error("controlled error"),
343348
)
344349
const [useError, getErrStream$] = bind((_: string) => errStream)
@@ -369,7 +374,7 @@ describe("connectFactoryObservable", () => {
369374
})
370375

371376
it("allows async errors to be caught in error boundaries with suspense", async () => {
372-
const errStream = new Subject()
377+
const errStream = new Subject<any>()
373378
const [useError, getErrStream$] = bind((_: string) => errStream)
374379

375380
const ErrorComponent = () => {

packages/core/src/bind/connectObservable.test.tsx

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import {
2+
act,
23
act as componentAct,
34
fireEvent,
45
render,
6+
renderHook,
57
screen,
68
} from "@testing-library/react"
7-
import { act, renderHook } from "@testing-library/react"
89
import React, { FC, StrictMode, Suspense, useEffect, useState } from "react"
10+
import { renderToPipeableStream } from "react-dom/server"
911
import {
1012
defer,
1113
EMPTY,
@@ -26,17 +28,16 @@ import {
2628
startWith,
2729
switchMapTo,
2830
} from "rxjs/operators"
29-
import { describe, it, beforeAll, afterAll, expect, vi } from "vitest"
31+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"
3032
import {
3133
bind,
3234
sinkSuspense,
3335
Subscribe,
3436
SUSPENSE,
3537
useStateObservable,
3638
} from "../"
37-
import { TestErrorBoundary } from "../test-helpers/TestErrorBoundary"
38-
import { renderToPipeableStream } from "react-dom/server"
3939
import { pipeableStreamToObservable } from "../test-helpers/pipeableStreamToObservable"
40+
import { TestErrorBoundary } from "../test-helpers/TestErrorBoundary"
4041

4142
const wait = (ms: number) => new Promise((res) => setTimeout(res, ms))
4243

@@ -93,8 +94,13 @@ describe("connectObservable", () => {
9394

9495
await wait(110)
9596

96-
expect(screen.queryByText("Result 1")).not.toBeNull()
97-
expect(screen.queryByText("Waiting")).toBeNull()
97+
vi.waitFor(
98+
() => {
99+
expect(screen.queryByText("Result 1")).not.toBeNull()
100+
expect(screen.queryByText("Waiting")).toBeNull()
101+
},
102+
{ timeout: 2000 },
103+
)
98104
sub.unsubscribe()
99105
})
100106

@@ -118,8 +124,13 @@ describe("connectObservable", () => {
118124

119125
await wait(110)
120126

121-
expect(screen.queryByText("Result 1")).not.toBeNull()
122-
expect(screen.queryByText("Waiting")).toBeNull()
127+
vi.waitFor(
128+
() => {
129+
expect(screen.queryByText("Result 1")).not.toBeNull()
130+
expect(screen.queryByText("Waiting")).toBeNull()
131+
},
132+
{ timeout: 2000 },
133+
)
123134
sub.unsubscribe()
124135
})
125136

@@ -183,9 +194,7 @@ describe("connectObservable", () => {
183194
const [useNumber] = bind(numberStream, 1)
184195
const [useString] = bind(stringStream, "a")
185196

186-
const BatchComponent: FC<{
187-
onUpdate: () => void
188-
}> = ({ onUpdate }) => {
197+
const BatchComponent: FC<{ onUpdate: () => void }> = ({ onUpdate }) => {
189198
const number = useNumber()
190199
const string = useString()
191200
useEffect(onUpdate)
@@ -329,8 +338,8 @@ describe("connectObservable", () => {
329338
{value === null
330339
? "default"
331340
: value instanceof Promise
332-
? "promise"
333-
: "wtf?"}
341+
? "promise"
342+
: "wtf?"}
334343
</div>
335344
)
336345
}
@@ -387,13 +396,17 @@ describe("connectObservable", () => {
387396

388397
await wait(10)
389398

390-
expect(screen.queryByText("Waiting")).toBeNull()
391-
expect(screen.queryByText("Result 1")).not.toBeNull()
399+
vi.waitFor(() => {
400+
expect(screen.queryByText("Waiting")).toBeNull()
401+
expect(screen.queryByText("Result 1")).not.toBeNull()
402+
})
392403

393404
fireEvent.click(screen.getByText(/NextVal/i))
394405

395-
expect(screen.queryByText("Result 2")).not.toBeNull()
396-
expect(screen.queryByText("Waiting")).toBeNull()
406+
vi.waitFor(() => {
407+
expect(screen.queryByText("Result 2")).not.toBeNull()
408+
expect(screen.queryByText("Waiting")).toBeNull()
409+
})
397410

398411
fireEvent.click(screen.getByText(/NextKey/i))
399412

@@ -405,17 +418,21 @@ describe("connectObservable", () => {
405418

406419
await wait(10)
407420

408-
expect(screen.queryByText("Result 1")).not.toBeNull()
409-
expect(screen.queryByText("Waiting")).toBeNull()
421+
vi.waitFor(() => {
422+
expect(screen.queryByText("Result 1")).not.toBeNull()
423+
expect(screen.queryByText("Waiting")).toBeNull()
424+
})
410425

411426
fireEvent.click(screen.getByText(/NextVal/i))
412427

413-
expect(screen.queryByText("Result 2")).not.toBeNull()
414-
expect(screen.queryByText("Waiting")).toBeNull()
428+
vi.waitFor(() => {
429+
expect(screen.queryByText("Result 2")).not.toBeNull()
430+
expect(screen.queryByText("Waiting")).toBeNull()
431+
})
415432
})
416433

417434
it("allows errors to be caught in error boundaries", () => {
418-
const errStream = new Subject()
435+
const errStream = new Subject<any>()
419436
const [useError] = bind(errStream, 1)
420437

421438
const ErrorComponent = () => {
@@ -441,7 +458,7 @@ describe("connectObservable", () => {
441458
})
442459

443460
it("allows sync errors to be caught in error boundaries with suspense, using source$", () => {
444-
const errStream = new Observable((observer) =>
461+
const errStream = new Observable<any>((observer) =>
445462
observer.error("controlled error"),
446463
)
447464
const [useError, errStream$] = bind(errStream)
@@ -468,7 +485,7 @@ describe("connectObservable", () => {
468485
})
469486

470487
it("allows sync errors to be caught in error boundaries with suspense, without using source$", () => {
471-
const errStream = new Observable((observer) =>
488+
const errStream = new Observable<any>((observer) =>
472489
observer.error("controlled error"),
473490
)
474491
const [useError] = bind(errStream)
@@ -495,7 +512,7 @@ describe("connectObservable", () => {
495512
})
496513

497514
it("allows sync errors to be caught in error boundaries when there is a default value", () => {
498-
const errStream = new Observable((observer) =>
515+
const errStream = new Observable<any>((observer) =>
499516
observer.error("controlled error"),
500517
)
501518
const [useError, errStream$] = bind(errStream, 0)
@@ -522,7 +539,7 @@ describe("connectObservable", () => {
522539
})
523540

524541
it("allows async errors to be caught in error boundaries with suspense", async () => {
525-
const errStream = new Subject()
542+
const errStream = new Subject<any>()
526543
const [useError, errStream$] = bind(errStream)
527544
const errStream$WithoutErrors = errStream$.pipe(catchError(() => NEVER))
528545

@@ -702,7 +719,7 @@ describe("connectObservable", () => {
702719
})
703720

704721
it("should throw an error if the stream completes without emitting while on SUSPENSE", async () => {
705-
const subject = new Subject()
722+
const subject = new Subject<any>()
706723
const [useValue, value$] = bind(subject)
707724
const errorCallback = vi.fn()
708725

packages/core/src/useStateObservable.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const useStateObservable = <O>(
2626
): Exclude<O, typeof SUSPENSE> => {
2727
const subscription = useSubscription()
2828
const [, setError] = useState()
29-
const callbackRef = useRef<Ref<O>>()
29+
const callbackRef = useRef<Ref<O> | undefined>(undefined)
3030

3131
if (!callbackRef.current) {
3232
const getValue = (src: StateObservable<O>) => {

packages/utils/src/createKeyedSignal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ export function createKeyedSignal<K, T, A extends any[]>(
7979
const payload = mapper
8080
? mapper(...args)
8181
: args.length === 2
82-
? args[1]
83-
: args[0]
82+
? args[1]
83+
: args[0]
8484
const key = keySelector ? keySelector(payload) : args[0]
8585
observersMap.get(key)?.forEach((o) => {
8686
o.next(payload)

0 commit comments

Comments
 (0)