A React hook to shape your components states.
import use from 'react-state-adapter'
const MyComponent = () => {
const myDialog = use(asDialog)(false)
return (
<>
<MyDialog
open={myDialog.isOpen}
onClose={myDialog.close}
/>
<button onClick={myDialog.open}>open</button>
</>
)
}
const asDialog = (value = false, set) => ({
isOpen: value,
open: () => set(true),
close: () => set(false),
toggle: () => set(prev => !prev)
})
Install via NPM:
npm i react-state-adapter
or Yarn:
yarn add react-state-adapter
An adapter is simply a function that takes:
- The primitive
value
of the state - The function to
set
a new value
and returns a more complex object, that can contains:
- derived properties
- custom methods
I want to shape a state around the "theme mode", that in my application is of type string; possible values for the state
are light
and dark
.
const asThemeMode = (mode = 'light', set) => ({
mode,
isDark: mode === 'dark',
toggle: () => {
set(mode === 'light' ? 'dark' : 'light')
}
})
I wrote an adapter that takes the primitive string value, and returns:
- a derived property
isDark
that explicitly transform the state into a more specific boolean information. - a custom method
toggle
that I can use to easily switch between the two string states. - the string state itself, named
mode
.
Import the use
custom hook from the library:
import use from 'react-state-adapter'
and declare a new state specifying the adapter to use.
const themeMode = use(asThemeMode)()
Eventually you can pass an initial value to override the one in your adapter:
const themeMode = use(asThemeMode)('dark')
Now, you can access all the previously defined properties.
<span>{themeMode.mode}</span> // 'dark'
<span>{themeMode.isDark}</span> // true
or use the custom methods:
<button onClick={themeMode.toggle}>click</button>
Additionally, the use
method will provide to your resulting state object:
- a property named
value
that contains the value of the underlying state. - a method named
set
to directly set the value of the underlying state.
You can easily define your own custom hooks by simply passing the adapter to the use
method:
const useThemeMode = use(asThemeMode)
or defining the adapter directly inside it:
const useThemeMode = use((value, set) => ({ ... }))
Use it with Typescript too:
import use, { Adapter, AdapterHook } from 'react-state-adapter'
interface ThemeMode {
mode: string
isDark: boolean
toggle: () => void
}
const asThemeMode: Adapter<string, ThemeMode> = (
(mode = 'light', set) => ({
mode,
isDark: mode === 'dark',
toggle: () => {
set(mode === 'light' ? 'dark' : 'light')
}
})
)
const useThemeMode: AdapterHook<string, ThemeMode> = (
use<string, ThemeMode>(asThemeMode)
)
const MyComponent = () => {
const themeMode: ThemeMode = useThemeMode('dark')
return (
<>
<span>{themeMode.mode} < /span>
<button onClick={themeMode.toggle} />
</>
)
}