Skip to content

Commit

Permalink
Merge pull request #25 from react18-tools/feat/support-initializer
Browse files Browse the repository at this point in the history
Feat/support initializer
  • Loading branch information
mayank1513 committed Jun 13, 2024
2 parents 285ab35 + ccccfe8 commit 73f1961
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 12 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ I've developed fantastic libraries leveraging React18 features using Zustand, an

As a solution, I set out to create a lightweight, bare minimum store that facilitates shared state even when importing components from separate files, optimizing tree-shaking.

> If you need fully featured state management solution, consider using Zustand with [`treeshakable`](https://github.com/react18-tools/treeshakable/)
> To understand the issue with treeshakability and importing from subpath, see - <https://treeshakable.vercel.app>
## Features

✅ Full TypeScript Support
Expand All @@ -28,6 +31,12 @@ Utilize this hook similarly to the `useState` hook. However, ensure to pass a un
const [state, setState] = useRGS<number>("counter", 1);
```

**_or_**

```tsx
const [state, setState] = useRGS<number>("counter", () => 1);
```

> For detailed instructions, see [Getting Started](./md-docs/1.getting-started.md)
## Using Plugins
Expand Down
6 changes: 3 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ We provide support for the latest minor version. Pull requests aimed at fixing s

| Version | Support Status |
| ------- | ------------------ |
| 1.0.x | :white_check_mark: |
| 0.2.x | :warning: |
| < 0.2 | :x: |
| 1.1.x | :white_check_mark: |
| 1.0.x | :warning: |
| < 1.0 | :x: |

## Patching Long-Term Support (LTS) Versions

Expand Down
8 changes: 8 additions & 0 deletions examples/nextjs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# nextjs-example

## 0.0.15

### Patch Changes

- Updated dependencies
- [email protected]
- [email protected]

## 0.0.14

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion examples/nextjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nextjs-example",
"version": "0.0.14",
"version": "0.0.15",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
8 changes: 8 additions & 0 deletions examples/remix/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# remix-example

## 0.0.15

### Patch Changes

- Updated dependencies
- [email protected]
- [email protected]

## 0.0.14

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion examples/remix/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "remix-example",
"version": "0.0.14",
"version": "0.0.15",
"private": true,
"sideEffects": false,
"type": "module",
Expand Down
8 changes: 8 additions & 0 deletions examples/vite/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# vite-example

## 0.0.15

### Patch Changes

- Updated dependencies
- [email protected]
- [email protected]

## 0.0.14

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion examples/vite/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vite-example",
"private": true,
"version": "0.0.14",
"version": "0.0.15",
"type": "module",
"scripts": {
"dev": "vite --port 3001",
Expand Down
6 changes: 6 additions & 0 deletions lib/r18gs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# r18gs

## 1.1.0

### Minor Changes

- Support initializer function. Now you can initialize the RGStore by supplying a function in place of constant.

## 1.0.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion lib/r18gs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "r18gs",
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
"private": false,
"version": "1.0.2",
"version": "1.1.0",
"description": "A simple yet elegant, light weight, react18 global store to replace Zustand for better tree shaking.",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
12 changes: 9 additions & 3 deletions lib/r18gs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style -- as ! operator is forbidden by eslint*/
import { createHook, createSetter, createSubcriber, globalRGS } from "./utils";

import type { SetStateAction } from "./utils";
import type { SetStateAction, ValueType } from "./utils";

export type { SetterArgType, SetStateAction, Plugin } from "./utils";

Expand All @@ -20,9 +20,15 @@ export type { SetterArgType, SetStateAction, Plugin } from "./utils";
* @param value - Initial value of the store.
* @returns - A tuple (Ordered sequance of values) containing the state and a function to set the state.
*/
const useRGS = <T>(key: string, value?: T): [T, SetStateAction<T>] => {
const useRGS = <T>(key: string, value?: ValueType<T>): [T, SetStateAction<T>] => {
/** Initialize the named store when invoked for the first time. */
if (!globalRGS[key]) globalRGS[key] = [value, [], createSetter(key), createSubcriber(key)];
if (!globalRGS[key])
globalRGS[key] = [
value instanceof Function ? value() : value,
[],
createSetter(key),
createSubcriber(key),
];

return createHook<T>(key);
};
Expand Down
6 changes: 4 additions & 2 deletions lib/r18gs/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type Subscriber = (l: Listener) => () => void;

export type SetterArgType<T> = T | ((prevState: T) => T);
export type SetStateAction<T> = (value: SetterArgType<T>) => void;
export type ValueType<T> = T | (() => T);

/**
* This is a hack to reduce lib size + readability + not encouraging direct access to globalThis
Expand Down Expand Up @@ -80,10 +81,11 @@ const initPlugins = async <T>(key: string, plugins: Plugin<T>[]) => {
/** Initialize the named store when invoked for the first time. */
export const initWithPlugins = <T>(
key: string,
value?: T,
value?: ValueType<T>,
plugins: Plugin<T>[] = [],
doNotInit = false,
) => {
value = value instanceof Function ? value() : value;
if (doNotInit) {
/** You will not have access to the setter until initialized */
globalRGS[key] = [value, [], null, createSubcriber(key)];
Expand Down Expand Up @@ -126,7 +128,7 @@ export const initWithPlugins = <T>(
*/
export const useRGSWithPlugins = <T>(
key: string,
value?: T,
value?: ValueType<T>,
plugins?: Plugin<T>[],
doNotInit = false,
): [T, SetStateAction<T>] => {
Expand Down
10 changes: 10 additions & 0 deletions md-docs/1.getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ You can access the same state across all client-side components using a unique k

> It's advisable to store your keys in a separate file to prevent typos and unnecessary conflicts.
### Initializing the state with a function

In some cases you might want to initialize the state with a function, for example, when reading from `localStorage`. We support initializer function as well.

```tsx
const [state, setState] = useRGS<number>("counter", () =>
typeof localStorage === "undefined" ? 1 : localStorage.getItem("counter") ?? 1,
);
```

### Example

```tsx
Expand Down

0 comments on commit 73f1961

Please sign in to comment.