unihooks v2.6.0
unihooks
Essential hooks collection for everyday react1 projects.
Principles
Unihooks are not bound to react and work with any hooks-enabled framework:
See any-hooks for the full list.
Unihooks follow useState
signature for intuitivity.
let [ state, actions ] = useValue( target?, init | update? )
Unihooks deliver value in reactive context, they're not mere wrappers for native API. Static hooks are avoided.
const MyComponent = () => { let ua = useUserAgent() } // ✘ − user agent never changes
const MyComponent = () => { let ua = navigator.userAgent } // ✔ − direct API must be used instead
Hooks
[value, setValue] = useChannel(key, init?, deps?)
Global value provider - useState
with value identified globally by key
.
Can be used as value store, eg. as application model layer without persistency. Also can be used for intercomponent communication.
init
can be a value or a function, and (re)applies if the key
(or deps
) changes.
import { useChannel } from 'unihooks'
function Component () {
let [users, setUsers] = useChannel('users', {
data: [],
loading: false,
current: null
})
setUsers({ ...users, loading: true })
// or as reducer
setUsers(users => { ...users, loading: false })
}
[value, setValue] = useStorage(key, init?, options?)
useChannel
with persistency to local/session storage. Subscribes to storage
event - updates if storage is changed from another tab.
import { useStorage } from 'unihooks'
function Component1 () {
const [count, setCount] = useStorage('my-count', 1)
}
function Component2 () {
const [count, setCount] = useStorage('my-count')
// count === 1
setCount(2)
// (↑ updates Component1 too)
}
function Component3 () {
const [count, setCount] = useStorage('another-count', (value) => {
// ...initialize value from store
return value
})
}
options
prefix
- prefix that's added to stored keys.storage
- manually pass session/local/etc storage.
Reference: useStore.
[action] = useAction(key, cb, deps?)
Similar to useChannel
, but used for storing functions. Different from useChannel
in the same way the useCallback
is different from useMemo
. deps
indicate if value must be reinitialized.
function RootComponent() {
useAction('load-content', async (slug, fresh = false) => {
const url = `/content/${slug}`
const cache = fresh ? 'reload' : 'force-cache'
const res = await fetch(url, { cache })
return await res.text()
})
}
function Content ({ slug = '/' }) {
let [content, setContent] = useState()
let [load] = useAction('load-content')
useEffect(() => load().then(setContent), [slug])
return html`
<article>${content}</article>
`
}
[value, setValue] = useSearchParam(name, init?)
Reflect value to location.search
. value
is turned to string via URLSearchParams.
To serialize objects or arrays, provide .toString
method or convert manually.
NOTE. Patches history.push
and history.replace
to enable pushstate
and replacestate
events.
function MyComponent () {
let [id, setId] = useSearchParam('id')
}
[n, reset] = useCountdown(startValue, interval=1000 | schedule?)
Countdown value from startValue
down to 0
with indicated interval
in ms. Alternatively, a scheduler function can be passed as schedule
argument, that can be eg. worker-timers-based implementation.
import { useCountdown } from 'unihooks'
import { setInterval, clearInterval } from 'worker-timers'
const Demo = () => {
const [count, reset] = useCountdown(30, fn => {
let id = setInterval(fn, 1000)
return () => clearInterval(id)
});
return `Remains: ${count}s`
};
[error, validate] = useValidate(validator: Function | Array, init? )
Provides validation functionality.
validator
is a function or an array of functionsvalue => error | true ?
.init
is optional initial value to validate.
function MyComponent () {
let [usernameError, validateUsername] = useValidate([
value => !value ? 'Username is required' : true,
value => value.length < 2 ? 'Username must be at least 2 chars long' : true
])
return <>
<input onChange={e => validateUsername(e.target.value) && handleInputChange(e) } {...inputProps}/>
{ usernameError }
</>
}
[props, field] = useFormField( options )
Form field state controller. Handles input state and validation. Useful for organizing controlled inputs or forms, a nice minimal replacement to form hooks libraries.
let [props, field] = useFormField({
name: 'password',
type: 'password',
validate: value => !!value
})
// to set new input value
useEffect(() => field.set(newValue))
return <input {...props} />
options
value
- initial input value.persist = false
- persist input state between sessions.validate
- custom validator for input, modifiesfield.error
. SeeuseValidate
.required
- if value must not be empty....props
- the rest of props is passed toprops
field
value
- current input value.error
- current validation error. Revalidates on blur,null
on focus.valid: bool
- is valid value, revalidates on blur.focus: bool
- if input is focused.touched: bool
- if input was focused.set(value)
- set input value.reset()
- reset form state to initial.validate(value)
- force-validate input.
[value, setValue] = useInput( element | ref )
Uncontrolled input element hook. Updates if input value changes.
Setting null
/ undefined
removes attribute from element.
Useful for organizing simple input controllers, for advanced cases see useFormField.
function MyButton() {
let ref = useRef()
let [value, setValue] = useInput(ref)
useEffect(() => {
// side-effect when value changes
}, [value])
return <input ref={ref} />
}
[state, setState] = useObservable(observable)
Observable as hook. Plug in any spect/v, observable, mutant, observ be free.
import { v } from 'spect/v'
const vCount = v(0)
function MyComponent () {
let [count, setCount] = useObservable(vCount)
useEffect(() => {
let id = setInterval(() => setCount(count++), 1000)
return () => clearInterval(id)
}, [])
return <>Count: { count }</>
}
For convenience, unihooks export current framework hooks. To switch hooks, use setHooks
- the default export.
import setHooks, { useState, useEffect } from 'unihooks'
import * as hooks from 'preact/hooks'
setHooks(hooks)
function Timer() {
let [count, setCount] = useState(0)
useEffect(() => {
let id = setInterval(() => setCount(c => ++c))
return () => clearInterval(id)
}, [])
}
Utility hooks, useful for high-order-hooks.
update = useUpdate()
Force-update component, regardless of internal state.
prev = usePrevious(value)
Returns the previous state as described in the React hooks FAQ.
See also
License
MIT
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago