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

Update the integration and add support signals #9

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
node_modules/

.pnpm-store/
ndt080 marked this conversation as resolved.
Show resolved Hide resolved
coverage/
19 changes: 19 additions & 0 deletions core/defineStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { listenKeys } from "nanostores";
import { useCallback } from "preact/hooks";

export function defineStore(store, options = {}, useSyncExternalStoreFn) {
ai marked this conversation as resolved.
Show resolved Hide resolved
let subscribe = useCallback(
(onChange) => {
return options.keys
? listenKeys(store, options.keys, onChange)
: store.listen(onChange);
},
[options.keys, store],
);

let get = useCallback(() => {
return (options.selector ?? ((s) => s))(store.get());
}, [options.selector, store]);

return useSyncExternalStoreFn(subscribe, get);
}
8 changes: 8 additions & 0 deletions core/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { StoreValue } from 'nanostores';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use types.ts in Nano Stores for type tests.

Can you move it to index.d.ts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains common type models for the "useStore" and "useStoreSignal" hooks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to put everything in single index.d.ts and index.js. This project is very small to use practices for huge projects.


export type StoreKeys<T> = T extends { setKey: (k: infer K, v: never) => unknown } ? K : never;

export interface UseStoreOptions<SomeStore, Value> {
keys?: StoreKeys<SomeStore>[];
selector?: (state: StoreValue<SomeStore>) => Value;
}
62 changes: 5 additions & 57 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,8 @@
import type { Store, StoreValue } from 'nanostores'
import type { Store, StoreValue } from "nanostores";

ndt080 marked this conversation as resolved.
Show resolved Hide resolved
type StoreKeys<T> = T extends { setKey: (k: infer K, v: any) => unknown }
? K
: never
import type { UseStoreOptions } from "./core/types";

export interface UseStoreOptions<SomeStore> {
/**
* Will re-render components only on specific key changes.
*/
keys?: StoreKeys<SomeStore>[]
}

/**
* Subscribe to store changes and get store’s value.
*
* Can be user with store builder too.
*
* ```js
* import { useStore } from 'nanostores/preact'
*
* import { router } from '../store/router'
*
* export const Layout = () => {
* let page = useStore(router)
* if (page.router === 'home') {
* return <HomePage />
* } else {
* return <Error404 />
* }
* }
* ```
*
* @param store Store instance.
* @returns Store value.
*/
export function useStore<SomeStore extends Store>(
export function useStore<SomeStore extends Store, Value = StoreValue<SomeStore>>(
store: SomeStore,
options?: UseStoreOptions<SomeStore>
): StoreValue<SomeStore>

/**
* Batch React updates. It is just wrap for React’s `unstable_batchedUpdates`
* with fix for React Native.
*
* ```js
* import { batch } from 'nanostores/preact'
*
* React.useEffect(() => {
* let unbind = store.listen(() => {
* batch(() => {
* forceRender({})
* })
* })
* })
* ```
*
* @param cb Callback to run in batching.
*/
export function batch(cb: () => void): void
options: UseStoreOptions<SomeStore, Value> = {},
): Value;
36 changes: 4 additions & 32 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
import { listenKeys } from 'nanostores'
import { useEffect, useState } from 'preact/hooks'
import { useSyncExternalStore } from "preact/compat";

export function useStore(store, opts = {}) {
let [, forceRender] = useState({})
let [valueBeforeEffect] = useState(store.get())
import { defineStore } from "./core/defineStore.js";

useEffect(() => {
valueBeforeEffect !== store.get() && forceRender({})
}, [])

useEffect(() => {
let batching, timer, unlisten
let rerender = () => {
if (!batching) {
batching = 1
timer = setTimeout(() => {
batching = undefined
forceRender({})
})
}
}
if (opts.keys) {
unlisten = listenKeys(store, opts.keys, rerender)
} else {
unlisten = store.listen(rerender)
}
return () => {
unlisten()
clearTimeout(timer)
}
}, [store, '' + opts.keys])

return store.get()
export function useStore(store, options = {}) {
return defineStore(store, options, useSyncExternalStore)
}
15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
"types": "./index.d.ts",
"exports": {
".": "./index.js",
"./package.json": "./package.json"
"./package.json": "./package.json",
"./signals": {
ai marked this conversation as resolved.
Show resolved Hide resolved
"import": "./signals/index.js",
"types": "./signals/index.d.ts"
}
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
Expand All @@ -36,7 +40,8 @@
],
"peerDependencies": {
"nanostores": "^0.9.0 || ^0.10.0 || ^0.11.0",
"preact": ">=10.0.0"
"preact": ">=10.0.0",
"@preact/signals": ">=1.0.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand All @@ -56,6 +61,7 @@
"nanodelay": "^2.0.2",
"nanostores": "^0.11.0",
"preact": "^10.23.1",
"@preact/signals": "^1.2.3",
"size-limit": "^11.1.4",
"tsx": "^4.16.5",
"typescript": "^5.5.4"
Expand Down Expand Up @@ -85,10 +91,11 @@
"size-limit": [
{
"import": {
"index.js": "{ useStore }",
"src/index.js": "{ useStore }",
"src/signals/index.js": "{ useStoreSignal }",
"nanostores": "{ map, computed }"
},
"limit": "921 B"
"limit": "999 B"
}
]
}
Loading
Loading