Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

to react 18 #18

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
603 changes: 421 additions & 182 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@types/node": "^17.0.0",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.1",
"@types/use-sync-external-store": "^0.0.3",
"@types/webpack": "^5.28.0",
"dtslint": "github:gcanti/dtslint",
"eslint": "^8.4.1",
Expand Down Expand Up @@ -108,5 +109,8 @@
"io-ts",
"react",
"isomorphic"
]
],
"dependencies": {
"use-sync-external-store": "^1.0.0-rc.0"
}
}
15 changes: 14 additions & 1 deletion src/http/ObservableResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { MonadObservable2 } from 'fp-ts-rxjs/MonadObservable'
import * as R from 'fp-ts-rxjs/Observable'
import type { ObservableEither } from 'fp-ts-rxjs/lib/ObservableEither'
import type { Applicative2 } from 'fp-ts/Applicative'
import type { Apply2 } from 'fp-ts/Apply'
import { Apply2, apS as apS_ } from 'fp-ts/Apply'
import type { Bifunctor2 } from 'fp-ts/Bifunctor'
import { Chain2, chainFirst as chainFirst_ } from 'fp-ts/Chain'
import * as E from 'fp-ts/Either'
Expand Down Expand Up @@ -312,6 +312,19 @@ export const filterOrElse: {
<E, A>(predicate: Predicate<A>, onFalse: (a: A) => E): (ma: ObservableResource<E, A>) => ObservableResource<E, A>
} = filterOrElseW

// -------------------------------------------------------------------------------------
// pipeable sequence S
// -------------------------------------------------------------------------------------

export const apS = apS_(Apply)

export const apSW: <A, N extends string, E2, B>(
name: Exclude<N, keyof A>,
fb: ObservableResource<E2, B>
) => <E1>(
fa: ObservableResource<E1, A>
) => ObservableResource<E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apS as any

// -------------------------------------------------------------------------------------
// utils
// -------------------------------------------------------------------------------------
Expand Down
16 changes: 15 additions & 1 deletion src/http/ReaderObservableResource.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ReaderObservableEither } from 'fp-ts-rxjs/ReaderObservableEither'
import type { MonadObservable3 } from 'fp-ts-rxjs/lib/MonadObservable'
import type { Applicative3 } from 'fp-ts/Applicative'
import type { Apply3 } from 'fp-ts/Apply'
import { Apply3, apS as apS_ } from 'fp-ts/Apply'
import type { Bifunctor3 } from 'fp-ts/Bifunctor'
import { Chain3, chainFirst as chainFirst_ } from 'fp-ts/Chain'
import type { Functor3 } from 'fp-ts/Functor'
Expand Down Expand Up @@ -324,3 +324,17 @@ export const bindW: <K extends string, R2, E2, A, B>(
) => <R1, E1>(
fa: ReaderObservableResource<R1, E1, A>
) => ReaderObservableResource<R1 & R2, E1 | E2, { [P in keyof A | K]: P extends keyof A ? A[P] : B }> = bind as any

// -------------------------------------------------------------------------------------
// pipeable sequence S
// -------------------------------------------------------------------------------------

export const apS = apS_(Applicative)

export const apSW: <A, N extends string, R2, E2, B>(
name: Exclude<N, keyof A>,
fb: ReaderObservableResource<R2, E2, B>
) => <R1, E1>(
fa: ReaderObservableResource<R1, E1, A>
) => ReaderObservableResource<R1 & R2, E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> =
apS as any
33 changes: 32 additions & 1 deletion src/http/Resource.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Applicative2 as RES } from 'fp-ts/Applicative'
import type { Apply2 } from 'fp-ts/Apply'
import { Apply2, apS as apS_ } from 'fp-ts/Apply'
import type { Bifunctor2 } from 'fp-ts/Bifunctor'
import * as E from 'fp-ts/Either'
import * as Eq from 'fp-ts/Eq'
Expand Down Expand Up @@ -387,3 +387,34 @@ export const chainW =
isDone(ma) ? f(ma.data) : ma

export const chain: <E, A, B>(f: (a: A) => Resource<E, B>) => (ma: Resource<E, A>) => Resource<E, B> = chainW

// -------------------------------------------------------------------------------------
// do notation
// -------------------------------------------------------------------------------------

// export const Do: Resource<never, Record<string, never>> = of(_.emptyRecord)

// export const bindTo = bindTo_(Functor)

// export const bind = bind_(Chain)

// /**
// * @since 2.8.0
// */
// export const bindW: <N extends string, A, E2, B>(
// name: Exclude<N, keyof A>,
// f: (a: A) => Either<E2, B>
// ) => <E1>(fa: Either<E1, A>) => Either<E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> =
// bind as any

// -------------------------------------------------------------------------------------
// pipeable sequence S
// -------------------------------------------------------------------------------------

export const apS = apS_(Apply)

export const apSW: <A, N extends string, E2, B>(
name: Exclude<N, keyof A>,
fb: Resource<E2, B>
) => <E1>(fa: Resource<E1, A>) => Resource<E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> =
apS as any
23 changes: 10 additions & 13 deletions src/react/useSelector.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { useEffect, useMemo, useState } from 'react'
import { distinctUntilChanged } from 'rxjs/operators'
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector'
import type * as MS from '../state'
import type { StoreName } from '../state/stores'

export const useSelector = <N extends StoreName, S, T>(store: MS.Store<N, S>, map: (s: S) => T): T => {
const [value, setValue] = useState<T>(() => map(store.initState))
return useSyncExternalStoreWithSelector<S, T>(
listener => {
const sub = store.state$.pipe(distinctUntilChanged()).subscribe(() => listener())

const state$ = store.state$

useEffect(() => {
const subscription = state$.pipe(distinctUntilChanged()).subscribe(s => setValue(map(s)))

return () => {
subscription.unsubscribe()
}
}, [state$, map])

return useMemo(() => value, [value])
return () => sub.unsubscribe()
},
() => store.state$.getValue(),
() => store.initState,
map
)
}
8 changes: 1 addition & 7 deletions website/docs/02-modules/01-http/01-data-fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@ sidebar_position: 1

The main purpose of this module is to expose an Algebraic Data Type (ADT) to manage the response of HTTP calls.

We don't consider safe design, like the following one:

```ts
const { data, error } = fetch('/api/user')
```

### Deep dive

If you want to deepen the topic, here are some useful resources:
If you want to deepen the topic (ADT), here are some useful resources:

- [Slaying a ui antipattern](https://medium.com/javascript-inside/slaying-a-ui-antipattern-in-fantasyland-907cbc322d2a)
- [Milano TS - Algebraic Data Type](https://www.youtube.com/watch?v=rs8rzYmKzVE) _video ita_