usage
next.js
TypeScript

Typescript usage

Installation

The Killua package lives in npm (opens in a new tab). To install the latest stable version, run the following command:

# npm
npm install killua
 
# yarn
yarn add killua

Setup provider

with page directory

Go to pages/_app.tsx (create it if it doesn't exist) and wrap the Component with the SSRKilluaProvider:

pages/_app.tsx
import { SSRKilluaProvider } from 'killua';
import type { AppProps } from 'next/app';
 
export default function App({ Component, pageProps }: AppProps) {
  return (
    <SSRKilluaProvider>
      <Component {...pageProps} />
    </SSRKilluaProvider>
  );
}

with app directory

  1. Go to your app/providers.tsx (create it if it doesn't exist) and wrap the Component with the SSRKilluaProvider:
app/providers.tsx
'use client';
 
import { SSRKilluaProvider } from 'killua';
 
export default function Providers({ children }: { children: React.ReactNode }) {
  return <SSRKilluaProvider>{children}</SSRKilluaProvider>;
}
  1. Go to your root layout page and wrap it with the Providers.tsx component:
pages/_app.tsx
import Providers from './providers';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" className="dark">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Create thunder

⚠️

Note that thunder refers to a key within local storage.

⚠️

Certainly, sensitive data should not be stored on local storage. The purpose of encrypting local storage in this method is to prevent regular users from having direct access to the data stored in local storage and also to prevent them from modifying it directly.

  1. Create a thunders directory for the thunder configuration.
  2. Create the thunder configuration file, for example: counter.ts.
  3. Set up the configuration:
thunders/counter.ts
import { thunder } from 'killua';
 
const thunderCounter = thunder({
  key: 'counter', // unique key for local storage, without starting with "thunder"
  encrypt: false as number, // if true, the data will be encrypted before being stored in local storage
  default: 1, // initial value for the thunder
  expire: 1, // // null to disable the expiration timer, or a number indicating the expiration time in minutes
  reducers: {
    // optional
    increment: (thunder: number) => thunder + 1,
    incrementWithPayload: (thunder: number, payload: number) =>
      thunder + payload,
    reset: () => 1,
  },
  selectors: {
    // optional
    getCounterPlusOne: (thunder: number) => thunder + 1,
    getCounterPlusPayload: (thunder: number, payload: number) =>
      thunder + payload,
  },
});
 
export { thunderCounter };

Use thunder

⚠️

The 'thunder' and the return values of methods on the 'selectors' object may be undefined during the first render in SSR. If you want to use their return values, check if 'isReadyInSsr' is true before accessing them.

⚠️

all desctructer property from thunder config is optional.

component/counter.ts
import { thunderCounter } from '../thunders/counter';
import { useKillua } from 'killua';
 
const Counter = () => {
  const {
    thunder: thunderCounterState,
    setThunder: thunderCounterSetState,
    reducers: thunderCounterReducers,
    selectors: thunderCounterSelectors,
    isReadyInSsr: thunderCounterIsReadyInSsr,
  } = useKillua(thunderCounter);
 
  return (
    <>
      <h2> Thunder </h2>
      <h2>
        Counter: {thunderCounterIsReadyInSsr ? thunderCounterState : 'wait ...'}
      </h2>
      <hr />
      <h2> Set Thunder </h2>
      <button onClick={() => thunderCounterSetState((prev: number) => prev + 1)}>
        Set Thunder with callback
      </button>
      <button onClick={() => thunderCounterSetState(12)}>
        Set Thunder without callback
      </button>
      <hr />
      <h2> Reducers </h2>
      <button onClick={() => thunderCounterReducers.increment()}>
        Increment
      </button>
      <button onClick={() => thunderCounterReducers.incrementWithPayload(5)}>
        Increment with payload
      </button>
      <button onClick={() => thunderCounterReducers.reset()}>Reset</button>
      <hr />
      <h2> Selectors </h2>
      <button
        onClick={() =>
          isReadyInSsr
            ? console.log(thunderCounterSelectors.getCounterPlusOne())
            : 'wait ...';
        }
      >
        Get counter with plus one
      </button>
      <button
        onClick={() =>
          isReadyInSsr
            ? console.log(thunderCounterSelectors.getCounterPlusPayload(10))
            : 'wait ...';
        }
      >
        Get counter with plus payload
      </button>
    </>
  );
};
 
export default Counter;