killua-beta v0.0.6
killua ·

killua is a local-storage management library for React applications.
Table of Contents
- Installation
- Features
- Create slice configuration file
- Get data
- Set data
- Use selectors
- Use reducers
- Using in SSR application
- Obfuscate data
- Expire timer
Installation
To install the latest stable version, run the following command:
# npm
npm install killua
# pnpm
pnpm install killua
# yarn
yarn add killuaFeatures
- Get data from localStorage
- Set data to localStorage
- Reducer for state management
- Selector for data access
- Expiration timer
- Schema validation
- Obfuscate data in localStorage
- Server-Side Compatibility
- TypeScript friendly
- Auto update in other tabs
- Auto update in other components
- Config file for configuration management
Usage
Create slice configuration file
that
slicerefers to a key within localStorage. 1. Create aslicesdirectory for the thunder configuration. 2. Create the slice configuration file, for example:counter.ts. 3. Set up the slice configuration:import { slice } from 'killua';
export const counterSlice = slice({ key: 'counter', // unique key for localStorage defaultClient: 1 as number // default value for client-side application });
### Get data
> Whatever the `useKillua` hook returns, the `slice` function also returns.
<br /> Use the useKillua hook within the React framework, and as long as you
don't have access to it, use the slice function.
- Within a React component, utilize the `useKillua` hook :
```tsx
import { useKillua } from "killua";
import { counterSlice } from "@/slices/counter";
export default function Component() {
const localstorageCounter = useKillua(counterSlice);
return (
<div>
<p>{counterSlice.get()}</p>
</div>
)
};- Outside of a React component, employ the
slicefunction :
import { counterSlice } from '@/slices/counter';
export function getCounter() {
return counterSlice.get();
}Set data
Whatever the
useKilluahook returns, theslicefunction also returns. Use the useKillua hook within the React framework, and as long as you don't have access to it, use the slice function.
- Within a React component, utilize the
useKilluahook :
import { useKillua } from "killua";
import { counterSlice } from "@/slices/counter";
export default function Component() {
const localstorageCounter = useKillua(counterSlice);
return (
<div>
{/* without callback */}
<button onClick={() => counterSlice.set(0)}>Set counter to zero</button>
{/* with callback */}
<button onClick={() => counterSlice.set((prev) => prev + 1)}>Increment counter</button>
</div>
)
};- Outside of a React component, employ the
slicefunction :
import { counterSlice } from '@/slices/counter';
// without callback
export function setCounterToZero() {
counterSlice.set(0);
}
// with callback
export function incrementCounter() {
counterSlice.set(prev => prev + 1);
}Use selectors
- To use a selector, simply add it to the slice config :
import { slice } from 'killua';
export const counterSlice = slice({
key: 'counter',
defaultClient: 1 as number,
selectors: {
getPlusOne: (value) => value + 1,
getPlusWithPayload: (value, payload: number) => value + payload
}
});- Within a React component, utilize the
useKilluahook :
import { useKillua } from "killua";
export default function Component() {
const localstorageCounter = useKillua(counterSlice);
return (
<div>
<p>{localstorageCounter.getPlusOne()}</p> {/* without payload */}
<p>{localstorageCounter.getPlusWithPayload(5)}</p> {/* with payload */}
</div>
)
};- Outside of a React component, employ the
slicefunction :
import { counterSlice } from '@/slices/counter';
// without payload
export function getCounterWithPlusOne() {
return counterSlice.getPlusOne();
}
// with payload
export function getCounterWithPlusWithPayload() {
return counterSlice.getPlusWithPayload(5);
}Use reducers
- To use a reducer, simply add it to the slice config :
import { slice } from 'killua';
export const counterSlice = slice({
key: 'counter',
defaultClient: 1 as number,
reducers: {
increment: (value) => value + 1,
incrementWithPayload: (value, payload: number) => value + payload
}
});- Within a React component, utilize the
useKilluahook :
import { useKillua } from "killua";
export default function Component() {
const localstorageCounter = useKillua(counterSlice);
return (
<div>
<button onClick={() => localstorageCounter.increment()}>Increment counter</button> {/* without payload */}
<button onClick={() => localstorageCounter.incrementWithPayload(5)}>Increment counter with payload</button> {/* with payload */}
</div>
)
};- Outside of a React component, employ the
slicefunction :
import { counterSlice } from '@/slices/counter';
// without payload
export function incrementCounter() {
counterSlice.increment();
}Using in SSR application
As long as the initial server-side rendering occurs and there is no access to localStorage,
defaultServerwill be returned. Later, when the client-side rendering takes place, data will be fetched from localStorage and returned. As long asdefaultServerexists in the config, both theuseKilluahook and theslicefunction will return a property namedisReady. If this value isfalse, it means that it is server-side and localStorage is not accessible, and the returned value isdefaultServer.If this value is true, it means that it is client-side and localStorage isaccessible, and the fetched value is from localStorage.
- add
defaultServerto the slice configuration :
import { slice } from 'killua';
export const counterSlice = slice({
key: 'counter',
defaultClient: 1 as number,
defaultServer: 2 // default value for server-side application
});- Within a React component, utilize the
useKilluahook :
'use client';
import { useKillua } from "killua";
export default function Component() {
const localstorageCounter = useKillua(counterSlice);
return (
<div>
{localstorageCounter.isReady ? <p>{localstorageCounter.get()}</p> : <p>Loading...</p>}
</div>
)
};- Outside of a React component, employ the
slicefunction :
import { counterSlice } from '@/slices/counter';
export function getCounter() {
// if is server-side ? return defaultServer : return localStorage value
return counterSlice.get();
}
// with payload
export function incrementCounterWithPayload() {
counterSlice.incrementWithPayload(5);
}Obfuscate data
As long as obsfacte is present in the slice config, your data is not protected but merely obfuscated. Avoid placing sensitive data on localStorage.
- To obfuscate localStorage data, simply add it to the slice config:
import { slice } from 'killua';
export const counterSlice = slice({
key: 'counter',
defaultClient: 1 as number,
obsfacte: true // obfuscate data in localStorage
});Expire timer
If the localStorage data expires at the moment when a user is on the website and the
useKilluahook is in use, the data will be immediately removed from localStorage. Subsequently, theuseKilluahook will update and return thedefaultClientvalue.If the user enters the site and the data has already expired, the
defaultClientvalue will be returned.
- To set an expiration time for localStorage data, simply add it to the slice config :
import { slice } from 'killua';
export const counterSlice = slice({
key: 'counter',
defaultClient: 1 as number,
expire: '1d-9h-24m-10s' // expire time for localStorage data (1 day, 9 hours, 24 minutes, 10 seconds)
});Schema validation
If
schemaexists in the configuration, when the localStorage is updated usingsetorreducers, the data will be validated against thatschema. If it is not valid, it will not be set on the localStorage. Ifschemais exists in the configuration, when the localStorage data is retrieved usingselectorsorget, and if it is validated against theschemaand found to be invalid, thedefaultClientvalue will be returned instead.
- To set a schema for localStorage data, simply add it to the slice config :
import { slice } from 'killua';
export const counterSlice = slice({
key: 'counter',
defaultClient: 1 as number,
schema: z.number().min(0).max(10) // zod schema or yup schema
});