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

feat(core): unstable_createStore #922

Merged
merged 11 commits into from
Feb 11, 2022
11 changes: 10 additions & 1 deletion src/core/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,23 @@ import {
DEV_GET_MOUNTED,
DEV_GET_MOUNTED_ATOMS,
DEV_SUBSCRIBE_STATE,
createStoreForExport,
} from './store'
import type { AtomState, Store, VersionObject } from './store'

export const Provider = ({
children,
initialValues,
scope,
unstable_createStore,
unstable_enableVersionedWrite,
}: PropsWithChildren<{
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>
scope?: Scope
/**
* This is an unstable feature to use exported createStore.
*/
unstable_createStore?: typeof createStoreForExport
/**
* This is an unstable experimental feature for React 18.
* When this is enabled, a) write function must be pure
Expand All @@ -49,7 +55,10 @@ export const Provider = ({
const scopeContainerRef = useRef<ScopeContainer>()
if (!scopeContainerRef.current) {
// lazy initialization
scopeContainerRef.current = createScopeContainer(initialValues)
scopeContainerRef.current = createScopeContainer(
initialValues,
unstable_createStore
)
if (unstable_enableVersionedWrite) {
scopeContainerRef.current.w = (write) => {
setVersion((parentVersion) => {
Expand Down
9 changes: 6 additions & 3 deletions src/core/contexts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createContext } from 'react'
import type { Context } from 'react'
import type { Atom, Scope } from './atom'
import { createStore } from './store'
import { createStore, createStoreForExport } from './store'
import type { Store } from './store'

type VersionedWrite = (write: (version?: object) => void) => void
Expand All @@ -12,9 +12,12 @@ export type ScopeContainer = {
}

export const createScopeContainer = (
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>
initialValues?: Iterable<readonly [Atom<unknown>, unknown]>,
unstable_createStore?: typeof createStoreForExport
): ScopeContainer => {
const store = createStore(initialValues)
const store = unstable_createStore
? unstable_createStore(initialValues).SECRET_INTERNAL_store
: createStore(initialValues)
return { s: store }
}

Expand Down
32 changes: 30 additions & 2 deletions src/core/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ export const createStore = (
version: VersionObject | undefined,
atom: WritableAtom<Value, Update, Result>,
update: Update
): void | Promise<void> => {
): Result => {
let isSync = true
const writeGetter: WriteGetter = <V>(
a: Atom<V>,
Expand Down Expand Up @@ -686,7 +686,7 @@ export const createStore = (
writingAtom: WritableAtom<Value, Update, Result>,
update: Update,
version?: VersionObject
): void | Promise<void> => {
): Result => {
const promiseOrVoid = writeAtomState(version, writingAtom, update)
flushPending(version)
return promiseOrVoid
Expand Down Expand Up @@ -898,3 +898,31 @@ export const createStore = (
}

export type Store = ReturnType<typeof createStore>

export const createStoreForExport = (
dai-shi marked this conversation as resolved.
Show resolved Hide resolved
initialValues?: Iterable<readonly [AnyAtom, AnyAtomValue]>
) => {
const store = createStore(initialValues)
const get = <Value>(atom: Atom<Value>) => {
const atomState = store[READ_ATOM](atom)
if ('e' in atomState) {
throw atomState.e // read error
}
if ('p' in atomState) {
return undefined // suspended
}
return atomState.v
}
const set = <Value, Update, Result extends void | Promise<void>>(
atom: WritableAtom<Value, Update, Result>,
update: Update
) => store[WRITE_ATOM](atom, update)
const sub = (atom: AnyAtom, callback: () => void) =>
store[SUBSCRIBE_ATOM](atom, callback)
return {
get,
set,
sub,
SECRET_INTERNAL_store: store,
}
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { Provider } from './core/Provider'
export { atom } from './core/atom'
export { useAtom } from './core/useAtom'
export { createStoreForExport as unstable_createStore } from './core/store'
export type { Atom, WritableAtom, PrimitiveAtom } from './core/atom'
export type {
Getter,
Expand Down