Skip to content

Commit 976d102

Browse files
committed
chore: fine-tune descriptions
1 parent a59bcad commit 976d102

5 files changed

Lines changed: 24 additions & 25 deletions

File tree

README.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,20 @@
77
<a href="https://redux-toolkit.js.org/"><img src="https://img.shields.io/badge/RTK-%5E2.11.2-764ABC?logo=redux&logoColor=white" alt="Redux Toolkit ^2.11.2"/></a>
88
</p>
99

10-
> Optimistic state management for Redux. No state copies, no checkpoints — optimistic state is derived at the selector level, like `git rebase`.
10+
> Optimistic state management for Redux. Optimistic state is derived at the selector level by replaying transitions on top of committed state, similar to `git rebase`.
1111
1212
---
1313

1414
## Why Optimistron?
1515

16-
Most optimistic-update libraries snapshot your entire state tree for every in-flight operation. Optimistron doesn't. It tracks lightweight **transitions** (stage, amend, commit, fail) alongside your reducer state and replays them at read-time through `selectOptimistic` — right where `reselect` memoization already lives.
16+
Optimistron tracks lightweight **transitions** (stage, amend, commit, fail) alongside your reducer state and replays them at read-time through `selectOptimistic`. No state snapshots or checkpoints are stored per operation.
1717

18-
Good fit for:
18+
Optimistron was designed around an **event-driven saga architecture** — components dispatch intent via `stage`, and sagas (or listener middleware) orchestrate the transition lifecycle. It can be used with thunks or direct component dispatches, but the separation between intent and orchestration is where it fits most naturally.
1919

20-
- **Offline-first** — transitions queue up while disconnected, conflicts resolve on reconnect
21-
- **Async dispatch** — thunks, sagas, listener middleware
22-
- **Large/normalized state** — no per-operation snapshots
20+
Designed for:
2321

24-
> Already happy with RTK Query's built-in optimistic updates? You probably don't need this.
22+
- **Offline-first** — transitions queue up while disconnected, conflicts resolve on reconnect
23+
- **Large/normalized state** — state is derived, not copied
2524

2625
---
2726

@@ -38,7 +37,7 @@ Think of each `optimistron()` reducer as a **git branch**:
3837

3938
`STAGE`, `AMEND`, `FAIL`, `STASH` never touch reducer state — they only modify the transitions list. The optimistic view updates because `selectOptimistic` re-derives on the next read.
4039

41-
No `isLoading` / `error` / `isOptimistic` flags. A pending transition _is_ loading. A failed one _is_ the error. One source of truth.
40+
There are no separate `isLoading` / `error` / `isOptimistic` flags — a pending transition represents the loading state, and a failed transition carries the error.
4241

4342
---
4443

@@ -165,15 +164,15 @@ const handler = listState<Todo>({ key: 'id', compare, eq });
165164
const crud = crudPrepare<Todo>('id');
166165
```
167166

168-
You can implement the `StateHandler` interface for any shape — the built-ins are just the common cases.
167+
Custom shapes can implement the `StateHandler` interface directly.
169168

170169
---
171170

172171
## Reducer Configuration
173172

174173
The 4th argument to `optimistron()` supports three modes:
175174

176-
**Auto-wired**zero boilerplate, handler routes payloads:
175+
**Auto-wired** — handler routes payloads by CRUD type:
177176

178177
```typescript
179178
optimistron('todos', initial, handler, {

usecases/basic/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ import { generateId, simulateAPIRequest } from '~usecases/lib/utils/mock-api';
1919
import { C, F, O } from '~usecases/lib/components/todo/CodeTags';
2020

2121
const description: UsecaseDescription = {
22-
subtitle: 'Component-level async — full transition lifecycle managed in the component.',
22+
subtitle: 'Component-level async — the transition lifecycle is managed directly in the component.',
2323
howItWorks: [
2424
<>Component dispatches <O>stage</O>, awaits the API, then <O>amend</O>s / <C>commit</C>s or <F>fail</F>s directly.</>,
25-
<>The full lifecycle (<O>stage</O> → API → <O>amend</O><C>commit</C> / <F>fail</F>) lives in the handler function — maximum visibility, minimum indirection.</>,
26-
<>Optimistic state is computed at the selector level via <code className="text-gray-400 text-[11px]">selectOptimistic</code> — no state copies, no checkpoints.</>,
25+
<>The full lifecycle (<O>stage</O> → API → <O>amend</O><C>commit</C> / <F>fail</F>) lives in the handler function.</>,
26+
<>Optimistic state is computed at the selector level via <code className="text-gray-400 text-[11px]">selectOptimistic</code>.</>,
2727
<>Failed transitions can be edited in-place — a new <O>stage</O> overwrites the failed one, restarting the lifecycle.</>,
2828
],
2929
};

usecases/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,14 @@ const Home: FC = () => (
181181

182182
<div className="text-left text-sm text-gray-400 leading-relaxed space-y-3 mb-8">
183183
<p>
184-
This demo is a <span className="text-gray-200">project management app</span> built to showcase Optimistron — each section uses a different
185-
state shape with full optimistic CRUD.
184+
A <span className="text-gray-200">project management app</span> demonstrating Optimistron — each section uses a different
185+
state shape with optimistic CRUD.
186186
</p>
187187
<p>
188-
<code className="text-[10px] text-fuchsia-400 bg-surface-3 px-1 py-0.5 rounded">singularState</code> powers the user profile,{' '}
189-
<code className="text-[10px] text-amber-400 bg-surface-3 px-1 py-0.5 rounded">nestedRecordState</code> drives project-grouped tasks,{' '}
190-
<code className="text-[10px] text-cyan-400 bg-surface-3 px-1 py-0.5 rounded">recordState</code> backs the flat epic list, and{' '}
191-
<code className="text-[10px] text-green-400 bg-surface-3 px-1 py-0.5 rounded">listState</code> powers the activity log.
188+
<code className="text-[10px] text-fuchsia-400 bg-surface-3 px-1 py-0.5 rounded">singularState</code> for the user profile,{' '}
189+
<code className="text-[10px] text-amber-400 bg-surface-3 px-1 py-0.5 rounded">nestedRecordState</code> for project-grouped tasks,{' '}
190+
<code className="text-[10px] text-cyan-400 bg-surface-3 px-1 py-0.5 rounded">recordState</code> for the flat epic list, and{' '}
191+
<code className="text-[10px] text-green-400 bg-surface-3 px-1 py-0.5 rounded">listState</code> for the activity log.
192192
</p>
193193
</div>
194194

usecases/sagas/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ import type { ActivityEntry, Epic, Profile, ProjectTodo } from '~usecases/lib/st
1616
import { C, F, O } from '~usecases/lib/components/todo/CodeTags';
1717

1818
const description: UsecaseDescription = {
19-
subtitle: 'Redux sagas — the most decoupled approach.',
19+
subtitle: 'Redux sagas — lifecycle orchestration decoupled from components.',
2020
howItWorks: [
21-
<>Component only dispatches <O>stage</O> — that's it. No async, no lifecycle awareness.</>,
21+
<>Component only dispatches <O>stage</O>. No async logic or lifecycle management in the component.</>,
2222
<>Saga watcher observes <O>stage</O> via <code className="text-gray-400 text-[11px]">takeEvery</code> and orchestrates the full lifecycle to <C>commit</C> or <F>fail</F>.</>,
23-
<>Maximum separation: UI fires intent, saga handles all orchestration — components are pure dispatch.</>,
23+
<>UI dispatches intent, saga handles orchestration — components only call dispatch.</>,
2424
<>Failed transitions can be edited in-place — a new <O>stage</O> overwrites the failed one, the saga picks it up automatically.</>,
2525
],
2626
};

usecases/thunks/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ import {
3131
import { C, F, O } from '~usecases/lib/components/todo/CodeTags';
3232

3333
const description: UsecaseDescription = {
34-
subtitle: 'Redux thunks — same lifecycle, cleaner components.',
34+
subtitle: 'Redux thunks — lifecycle logic moved from components into thunks.',
3535
howItWorks: [
36-
<>Component dispatches a thunk — no transition management in the component at all.</>,
36+
<>Component dispatches a thunk. No transition management in the component.</>,
3737
<>Each thunk encapsulates the full lifecycle: <O>stage</O> → API → <O>amend</O><C>commit</C> / <F>fail</F>.</>,
38-
<>Same optimistic behavior as Basic — components only call <code className="text-gray-400 text-[11px]">dispatch(thunk(item))</code>.</>,
38+
<>Components only call <code className="text-gray-400 text-[11px]">dispatch(thunk(item))</code>.</>,
3939
<>Failed transitions can be edited in-place — a new <O>stage</O> overwrites the failed one, restarting the lifecycle.</>,
4040
],
4141
};

0 commit comments

Comments
 (0)