Skip to content

Commit

Permalink
Merge pull request #20 from react18-tools/refactor
Browse files Browse the repository at this point in the history
Refactor
  • Loading branch information
mayank1513 committed Apr 30, 2024
2 parents e95286d + 7b71f71 commit 7219caf
Show file tree
Hide file tree
Showing 31 changed files with 550 additions and 265 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# These are supported funding model platforms

github: [mayank1513] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
polar: mayank1513
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
Expand Down
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

98 changes: 22 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,119 +4,65 @@

## Motivation

I have built wonderful libraries utilizing React18 features using Zustand. They worked awesome. However, when I try importing from specific folder for better tree-shaking, the libraries fail. This is because, for each import a separate zustand store is created. This actually increases the package size also.
I've developed fantastic libraries leveraging React18 features using Zustand, and they performed admirably. However, when attempting to import from specific folders for better tree-shaking, the libraries encountered issues. Each import resulted in a separate Zustand store being created, leading to increased package size.

Thus, I decided to create a bare minimum, ultra-light store that creates shared state even while importing components from separate files for better treeshaking.
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.

## Features

✅ Full TypeScript Support

✅ Unleash the full power of React18 Server components

Works with all build systems/tools/frameworks for React18
Compatible with all build systems/tools/frameworks for React18

Doccumented with [Typedoc](https://react18-tools.github.io/react18-global-store) ([Docs](https://react18-tools.github.io/react18-global-store))
Documented with [Typedoc](https://react18-tools.github.io/react18-global-store) ([Docs](https://react18-tools.github.io/react18-global-store))

✅ Next.js, Vite and Remix examples
Examples for Next.js, Vite, and Remix

## Install
## Simple Global State Shared Across Multiple Components

> A canonical package with longer name is also published `react18-global-store`
```bash
$ pnpm add r18gs
```

or

```bash
$ npm install r18gs
```

or

```bash
$ yarn add r18gs
```

## Usage

Use this hook similar to `useState` hook.

The difference is that you need to pass an unique key - unique across the app to identify
and make this state accessible to all client components.
Utilize this hook similarly to the `useState` hook. However, ensure to pass a unique key, unique across the app, to identify and make this state accessible to all client components.

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

You can access the same state across all client side components using unique key.
> For detailed instructions, see [Getting Started](./md-docs/1.getting-started.md)
> It is recommended to store your keys in separate file to avoid typos and unnecessary conflicts.
## Using Plugins

### Example
Enhance the functionality of the store by leveraging either the `create` function, `withPlugins` function, or the `useRGSWithPlugins` hook from `r18gs/dist/with-plugins`, enabling features such as storing to local storage, among others.

```tsx
// constants/global-states.ts
export const COUNTER = "counter";
```
// store.ts
import { create } from "r18gs/dist/with-plugins";
import { persist } from "r18gs/dist/plugins"; /** You can create your own plugin or import third-party plugins */

```tsx
// components/display.tsx
"use client";

import useRGS from "r18gs";
import { COUNTER } from "../constants/global-states";

export default function Display() {
const [count] = useRGS<number>(COUNTER);
return (
<div>
<h2>Client component 2</h2>
<b>{count}</b>
</div>
);
}
export const useMyPersistentCounterStore = create<number>("persistent-counter", 0, [persist()]);
```

Now, you can utilize `useMyPersistentCounterStore` similarly to `useState` without specifying an initial value.

```tsx
// components/counter.tsx
"use client";

import useRGS from "r18gs";
import { COUNTER } from "../constants/global-states";

export default function Counter() {
const [count, setCount] = useRGS(COUNTER, 0);
return (
<div>
<h2>Clinet component 1</h2>
<input
onChange={e => {
setCount(parseInt(e.target.value.trim()));
}}
type="number"
value={count}
/>
</div>
);
}
const [persistedCount, setPersistedCount] = useMyPersistentCounterStore();
```

> For detailed instructions, see [Leveraging Plugins](./md-docs/2.leveraging-plugins.md)
## Contributing

See [contributing.md](/contributing.md)

### 🤩 Don't forger to star [this repo](https://github.com/mayank1513/react18-global-store)!
### 🤩 Don't forget to star [this repo](https://github.com/mayank1513/react18-global-store)!

Want hands-on course for getting started with Turborepo? Check out [React and Next.js with TypeScript](https://mayank-chaudhari.vercel.app/courses/react-and-next-js-with-typescript) and [The Game of Chess with Next.js, React and TypeScrypt](https://www.udemy.com/course/game-of-chess-with-nextjs-react-and-typescrypt/?referralCode=851A28F10B254A8523FE)
Interested in hands-on courses for getting started with Turborepo? Check out [React and Next.js with TypeScript](https://mayank-chaudhari.vercel.app/courses/react-and-next-js-with-typescript) and [The Game of Chess with Next.js, React and TypeScript](https://www.udemy.com/course/game-of-chess-with-nextjs-react-and-typescript/?referralCode=851A28F10B254A8523FE)

![Repo Stats](https://repobeats.axiom.co/api/embed/ec3e74d795ed805a0fce67c0b64c3f08872e7945.svg "Repobeats analytics image")

## License

Licensed as MIT open source.
Licensed under the MPL 2.0 open source license.

<hr />

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

## 0.0.12

### Patch Changes

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

## 0.0.11

### 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.11",
"version": "0.0.12",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
11 changes: 11 additions & 0 deletions examples/remix/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# remix-example

## 0.0.12

### Patch Changes

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

## 0.0.11

### 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.11",
"version": "0.0.12",
"private": true,
"sideEffects": false,
"type": "module",
Expand Down
11 changes: 11 additions & 0 deletions examples/vite/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# vite-example

## 0.0.12

### Patch Changes

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

## 0.0.11

### 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.11",
"version": "0.0.12",
"type": "module",
"scripts": {
"dev": "vite --port 3001",
Expand Down
15 changes: 15 additions & 0 deletions lib/r18gs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# r18gs

## 1.0.0

### Major Changes

- Removed `serverValue` field as it should always be same as `value`. For more details please check out documentation of useSyncExternalStore hook provided by react.

### Minor Changes

- Added persist plugin to create state that is persisted and synced between browser contexts.
- Added `useRGSWithPlugins` hook to support extending the store functionality with plugins.

### Patch Changes

- Refactored to reduce bundle size and improve stability and reduce likelyhood of bugs.

## 0.2.0

### Minor Changes
Expand Down
5 changes: 0 additions & 5 deletions lib/r18gs/index.ts

This file was deleted.

19 changes: 13 additions & 6 deletions 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": "0.2.0",
"version": "1.0.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 All @@ -19,7 +19,7 @@
},
"homepage": "https://react18-global-store.vercel.app/",
"sideEffects": false,
"license": "MIT",
"license": "MPL-2.0",
"scripts": {
"test": "vitest run --coverage",
"build": "tsup src && tsc -p tsconfig-build.json",
Expand All @@ -42,6 +42,10 @@
"tsconfig": "workspace:*",
"tsup": "^8.0.2",
"typedoc": "^0.25.13",
"typedoc-plugin-mdn-links": "^3.1.23",
"typedoc-plugin-missing-exports": "^2.2.0",
"typedoc-plugin-rename-defaults": "^0.7.0",
"typedoc-plugin-zod": "^1.1.2",
"typescript": "^5.4.5",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.5.2"
Expand All @@ -50,10 +54,13 @@
"@types/react": "16.8 - 18",
"react": "16.8 - 18"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/mayank1513"
},
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/mayank1513"
},
"https://pages.razorpay.com/mayank1513"
],
"keywords": [
"react18-global-store",
"nextjs",
Expand Down
3 changes: 0 additions & 3 deletions lib/r18gs/server.ts

This file was deleted.

28 changes: 26 additions & 2 deletions lib/r18gs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
import useRGS from "./use-rgs";
/* 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";

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

export default useRGS;
/**
* Use this hook similar to `useState` hook.
* The difference is that you need to pass a
* unique key - unique across the app to make
* this state accessible to all client components.
*
* @example
* ```tsx
* const [state, setState] = useRGS<number>("counter", 1);
* ```
*
* @param key - Unique key to identify the store.
* @param value - Initial value of the store.
* @returns - A tuple (Ordered sequance of values) containing the state and a function to set the state.
*/
export default function useRGS<T>(key: string, value?: T): [T, SetStateAction<T>] {
/** Initialize the named store when invoked for the first time. */
if (!globalRGS[key]) globalRGS[key] = [value, [], createSetter(key), createSubcriber(key)];

return createHook<T>(key);
}
1 change: 1 addition & 0 deletions lib/r18gs/src/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./persist";
31 changes: 0 additions & 31 deletions lib/r18gs/src/plugins/persist-and-sync.ts

This file was deleted.

Loading

0 comments on commit 7219caf

Please sign in to comment.