https://github.com/xiel/outer-hooks
Powerful and composable hooks that work in Node & Browser.
https://github.com/xiel/outer-hooks
functional-programming hook hooks node typescript
Last synced: 2 months ago
JSON representation
Powerful and composable hooks that work in Node & Browser.
- Host: GitHub
- URL: https://github.com/xiel/outer-hooks
- Owner: xiel
- License: mit
- Created: 2021-10-03T10:00:51.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2023-01-06T22:32:33.000Z (about 3 years ago)
- Last Synced: 2025-11-01T09:02:53.445Z (5 months ago)
- Topics: functional-programming, hook, hooks, node, typescript
- Language: TypeScript
- Homepage:
- Size: 1.26 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# OuterHooks 💫
[](https://www.npmjs.com/package/@xiel/outer-hooks)

Create function components using powerful and composable hooks.
If you know and love [hooks from React](https://reactjs.org/docs/hooks-intro.html), you already know the main API of OuterHooks as they are very alike.
### Differences to React
- OuterHooks is plain JavaScript/TypeScript
- No JSX here – does not render to the DOM or any UI really
- Only compose logic using native & custom hooks
- Life cycle hooks like useEffect also run in Node
## Install
```
yarn add @xiel/outer-hooks
```
#### Warning: Work in progress
This library is still in **beta**. It works, is well tested and actively being developed. But the API is not 100% stable yet.
## Hooks
### Native Hooks
- useState, useRef, useMemo, useCallback, useReducer, useEffect, useLayoutEffect, ...
For now please check the React [Hooks API reference](https://reactjs.org/docs/hooks-reference.html) as they work exactly the same in OuterHooks.
### Custom Hooks
By composing native hooks, you are creating a custom hook. Native hooks and custom hooks can be composed and nested.
#### Example
```ts
// Define a custom hook
function useCustomHook() {
const [currentState, setState] = useState(0)
useEffect(() => {
if (currentState < 5) {
setState(currentState + 1)
}
}, [currentState])
return currentState
}
// Run the hook
const custom = runHook(useCustomHook)
// Gets called every time the hook has run
// In this example it will get called with the values 0, 1, 2, 3, 4, 5
custom.on('update', (value) => console.log(value))
// Gets called when the hook was destroyed
custom.on('destroy', (error) => console.error('destroyed'))
```
#### runHook(fn)
runHook(fn) returns the following interface, which lets you await the next value, await effects, read the latest value and subscribe to updates to your hook.
```ts
export interface Root {
displayName: string
/**
* Resolves once the hooks has rendered.
* Might resolve after being intermediately suspended.
*/
value: Promise
/**
* Resolves once all side effects have run (cleanups, useLayoutEffects and useEffects)
*/
effects: Promise
/**
* Returns the current value of the ran hook (outermost custom `useXYZ` hook)
* This might return undefined or a stole/older value while the hook is suspended.
* Recommended: Use the value promise to get the latest value.
*/
currentValue?: HookValue
/**
* While the hook is suspended, this will return true
*/
isSuspended: boolean
/**
* If the hook was destroyed (by error or externally), this will return true
*/
isDestroyed: boolean
/**
* Resolves after all cleanup functions have run
*/
isDestroyedPromise: Promise | undefined
/**
* Re-run the hook with new props
*/
render: RenderFn
/**
* Re-run the hook with (partially) new props.
*/
update: UpdateFn
/**
* Subscribe to hook updates
*/
on: (
type: T,
subscription: SubscriptionTypes[T]
) => UnsubscribeFn
/**
* Unsubscribe from hook updates
*/
off: (
type: T,
subscription: SubscriptionTypes[T]
) => void
/**
* Destroy the hook.
* This will run all cleanup functions and reject the value promise
*/
destroy(reason?: unknown): Promise
}
```