Skip to content

Commit e552498

Browse files
committed
RELEASING: Releasing 2 package(s)
Releases: kosha@1.2.0 @repo/shared@0.0.12
1 parent af4d62a commit e552498

File tree

6 files changed

+117
-38
lines changed

6 files changed

+117
-38
lines changed

.changeset/moody-poets-agree.md

Lines changed: 0 additions & 25 deletions
This file was deleted.

README.md

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
![Bundle Size](https://img.shields.io/bundlephobia/minzip/kosha)
99
[![Gitpod Ready](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/from-referrer/)
1010

11-
### **A Modern, Lightweight, and High-Performance State Management Library for React**
11+
> **_⚡Kosha_**: **A Modern, Lightweight, and High-Performance State Management Library for React**
1212
1313
**Kosha** is a production-ready, minimalistic global state management solution for modern React applications. At just **\~450 bytes minzipped**, it's optimized for performance-critical applications, full React 18+ support, and clean developer ergonomics.
1414

@@ -21,6 +21,7 @@ Live demo: [https://kosha-six.vercel.app](https://kosha-six.vercel.app)
2121
- [🚀 Features](#-features)
2222
- [📦 Installation](#-installation)
2323
- [🧑‍💻 Usage](#-usage)
24+
- [🧰 Immer Middleware](#-immer-middleware)
2425
- [⚖️ Zustand Comparison](#️-why-choose-kosha-over-zustand)
2526
- [📁 Examples](#-examples)
2627
- [❓ FAQ](#-faq)
@@ -125,22 +126,88 @@ const increment = useKosha(state => state.increment);
125126
const { count, increment } = useKosha(({ count, increment }) => ({ count, increment }));
126127
```
127128

128-
### 4. Enable External Set Access (Optional)
129+
### 4. Update Outside React
129130

130-
```tsx
131-
const useKosha = create(set => ({
132-
count: 0,
133-
increment: () => set(state => ({ count: state.count + 1 })),
134-
set, // manually exposed
131+
```ts
132+
useKosha.getState().increment();
133+
```
134+
135+
## ⚠️ Avoid In-Place Mutations
136+
137+
Kosha detects changes using shallow comparison (`JSON.stringify`) between the **previous and new result of the selector**.
138+
If you mutate state **in-place** and return the same object reference, **listeners will not be triggered**, and your UI will not re-rendereven though the state has technically changed.
139+
140+
### 🔴 Problem Example
141+
142+
```ts
143+
create(set => ({
144+
todos: [],
145+
addTodo: item =>
146+
set(state => {
147+
state.todos.push(item); // ❌ in-place mutation
148+
return state; // same reference!
149+
}),
135150
}));
136151
```
137152

138-
### 5. Update Outside React
153+
### Correct WayReturn a New Object
139154

140155
```ts
141-
useKosha.getState().increment();
156+
create(set => ({
157+
todos: [],
158+
addTodo: item =>
159+
set(state => ({
160+
...state,
161+
todos: [...state.todos, item], // ✅ returns a new object
162+
})),
163+
}));
142164
```
143165

166+
### ✅ Even BetterUse Immer
167+
168+
```ts
169+
import { produce } from "immer";
170+
171+
create(set => ({
172+
todos: [],
173+
addTodo: item =>
174+
set(
175+
produce(state => {
176+
state.todos.push(item);
177+
}),
178+
),
179+
}));
180+
```
181+
182+
> ℹ️ Kosha does not bundle `immer` by default, but you can use it safely with your own setup or use immer middleware.
183+
184+
---
185+
186+
## 🧰 Immer Middleware
187+
188+
Kosha provides a convenient **immer middleware** to simplify immutable state updates by enabling you to write mutative logic inside the store setter. It internally applies `immer`'s `produce` function automatically.
189+
190+
Example usage:
191+
192+
```ts
193+
import { create } from "kosha";
194+
import { immer } from "kosha/middleware";
195+
196+
const useKosha = create(
197+
immer(set => ({
198+
todos: [],
199+
addTodo: (item: string) =>
200+
set(state => {
201+
state.todos.push(item); // safe mutable update with immer middleware
202+
}),
203+
})),
204+
);
205+
```
206+
207+
This middleware allows you to write concise, mutable-looking update code while keeping the state immutable under the hood.
208+
209+
You can combine `immer` middleware with other middlewares like `persist` for powerful state management.
210+
144211
---
145212

146213
## ⚖️ Why Choose Kosha Over Zustand?
@@ -187,11 +254,15 @@ const useStore = create(set => ({
187254

188255
Yes. Middleware support is built-in. A working persist middleware is included. You can easily build your own or extend with logging, devtools, etc.
189256

190-
### 4. Can I use it with `Set`, `Map`, or `Date` objects?
257+
### 4. My state updates, but components dont re-render. Why?
258+
259+
You might be mutating the existing state object **in-place** instead of returning a new one. Kosha relies on reference comparison (`JSON.stringify`) to detect changes. Always return a new object, or use libraries like **immer** or the **immer middleware** from `kosha/middleware` to handle immutable updates safely.
260+
261+
### 5. Can I use it with `Set`, `Map`, or `Date` objects?
191262

192263
While `Date` serializes fine, **avoid storing `Set` or `Map`** directly in global state, since Kosha uses `JSON.stringify` to diff selector outputs. Use arrays or plain objects instead for best results.
193264

194-
### 5. Isnt JSON.stringify unreliable because key order might change?
265+
### 6. Isnt JSON.stringify unreliable because key order might change?
195266

196267
Noin Kosha, youre comparing outputs of the same selector function across renders. Since the order of keys in JavaScript objects is preserved in deterministic function outputs, JSON.stringify remains stable and reliable in this context.
197268

lib/CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# kosha
22

3+
## 1.2.0
4+
5+
### Minor Changes
6+
7+
- 303dd10: ✨ **Feature:** Introduced `immer` middleware for Kosha
8+
9+
You can now opt-in to immutable state updates via [Immer](https://github.com/immerjs/immer).
10+
11+
This enables writing simpler, more intuitive state updates using mutable-like syntax:
12+
13+
```ts
14+
const useStore = create(
15+
immer(set => ({
16+
count: 0,
17+
increment: () =>
18+
set(state => {
19+
state.count++;
20+
}),
21+
})),
22+
);
23+
```
24+
25+
💡 Listeners will still be triggered correctly as Immer tracks mutations internally and returns new state safely.
26+
27+
Use with care: avoid returning any value from the mutator function to ensure Immer can do its job properly.
28+
329
## 1.1.2
430

531
### Patch Changes

lib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "kosha",
33
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
44
"private": false,
5-
"version": "1.1.2",
5+
"version": "1.2.0",
66
"description": "A modern, lightweight, fast, and powerful global state management library for modern React.js projects. ",
77
"license": "MPL-2.0",
88
"main": "./dist/index.js",

packages/shared/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# @repo/shared
22

3+
## 0.0.12
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [303dd10]
8+
- kosha@1.2.0
9+
310
## 0.0.11
411

512
### Patch Changes

packages/shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@repo/shared",
3-
"version": "0.0.11",
3+
"version": "0.0.12",
44
"private": true,
55
"sideEffects": false,
66
"main": "./dist/index.js",

0 commit comments

Comments
 (0)