Make state shareable
without using contextMake state persistent
using localStorageMake state accessible
without re-rendering componentMake state extensible
using your own custom storage
# Using npm
npm i -S @rpgtec/use-storage
# Using yarn
yarn add @rpgtec/use-storage
import { useLocalStorage, setLocalStorage } from '@rpgtec/use-storage'
function App() {
// Set the key name as the first argument
const [count, setCount] = useLocalStorage('count', 0)
return (
<div>
{/* Usage is almost the same as setState */}
<div>count: {count}</div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(0)}>Reset</button>
{/* The state is remembered even if you reload */}
<button onClick={() => window.location.reload()}>Reload</button>
</div>
)
}
// You can access the state without dependencies
setInterval(() => setLocalStorage('count', x => x + 1), 1000)
const [state, setState] = useStorage(key, initialState, storage)
The usage of state
and setState
is almost the same as that of useState
name | type | description |
---|---|---|
key | string |
Set a key name to identify what the state is. Synchronize states with the same key. |
initialState | any |
Return initialState when the state is undefined. If initialState is a function , return the result of the function call. |
storage | object |
[Optional] default storage is a wrapper of simple object in memory. You can also use your own custom storage. |
useStorage(key, initialState, storage)
getStorage(key, initialState, storage)
setStorage(key, value, storage)
useLocalStorage(key, initialState)
getLocalStorage(key, initialState)
setLocalStorage(key, value)
useSessionStorage(key, initialState)
getSessionStorage(key, initialState)
setSessionStorage(key, value)
import { useStorage } from '@rpgtec/use-storage'
function ComponentA() {
// Set the key name as the first argument
const [query, setQuery] = useStorage('query', '')
return <input value={query} onChange={event => setQuery(event.target.value)} />
}
function ComponentB() {
// Synchronize states with the same key
const [query, setQuery] = useStorage('query', '')
return <input value={query} onChange={event => setQuery(event.target.value)} />
}
import { useLocalStorage } from '@rpgtec/use-storage'
function ComponentA() {
// To make a persistent state, use useLocalStorage instead of useStorage
const [query, setQuery] = useLocalStorage('query', '')
return <input value={query} onChange={event => setQuery(event.target.value)} />
}
function ComponentB() {
// A persistent state is also synchronized with the state of the same key
// And, state is remembered even if you reload
const [query, setQuery] = useLocalStorage('query', '')
return <input value={query} onChange={event => setQuery(event.target.value)} />
}
import { useStorage, setStorage, getStorage } from '@rpgtec/use-storage'
function CountView() {
console.log('Render: CountView') //=> re-render when the count is updated
const [count] = useStorage('count', 0)
return <div>count: {count}</div>
}
// No need to re-render this component when the count is updated.
// So, use setStorage / getStorage instead of useStorage.
function CountTool() {
console.log('Render: CountTool') //=> only first rendering
return (
<div>
<button onClick={() => setStorage('count', x => x + 1)}>count up</button>
<button onClick={() => setStorage('count', 0)}>count reset</button>
<button onClick={() => console.log(getStorage('count'))}>get count</button>
</div>
)
}
import { useStorage } from '@rpgtec/use-storage'
// Storage must have get / set methods
const numberOnlyStorage = (obj => ({
get: key => {
return obj[key]
},
set: (key, value = '') => {
// Convert value to numbers only!
obj[key] = value.replace(/[^0-9]/g, '').replace(/^0+([0-9])/, '$1') || '0'
return obj[key]
},
}))({})
function Component() {
const [number, setNumber] = useStorage('number', '0', numberOnlyStorage)
return <input value={number} onChange={event => setNumber(event.target.value)} />
}
Happy hacking!