Skip to content

Commit

Permalink
Added slices pattern example (#194)
Browse files Browse the repository at this point in the history
* added slices pattern example

* uninstall devtools

* revert pnpm lock change
  • Loading branch information
mneveroff authored Jan 17, 2025
1 parent 65a1c99 commit 2c2494d
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ PRs are welcome! [pnpm](https://pnpm.io/) is used as a package manager. Run `pnp
- [canUndo, canRedo, undoDepth, redoDepth](https://codesandbox.io/s/zundo-canundo-and-undodepth-l6jclx?file=/src/App.tsx:572-731)
- [with deep equal](https://codesandbox.io/p/sandbox/zundo-deep-equal-qg69lj)
- [with input](https://stackblitz.com/edit/vitejs-vite-jqngm9?file=src%2FApp.tsx)
- [with slices pattern](https://codesandbox.io/p/sandbox/pttx6c)

## Migrate from v1 to v2

Expand Down
2 changes: 1 addition & 1 deletion examples/web/next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
147 changes: 147 additions & 0 deletions examples/web/pages/slices.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import type { StateCreator } from 'zustand';
import type { TemporalState } from 'zundo';
import { temporal } from 'zundo';
import { create } from 'zustand';
import { useShallow } from 'zustand/shallow';
import { useStoreWithEqualityFn } from 'zustand/traditional';

interface BearSlice {
bears: number
addBear: () => void
eatFish: () => void
}

interface FishSlice {
fishes: number
addFish: () => void
}

const createBearSlice: StateCreator<
BearSlice & FishSlice,
[],
[],
BearSlice
> = (set) => ({
bears: 0,
addBear: () => set((state) => ({ bears: state.bears + 1 })),
removeBear: () => set((state) => ({ bears: state.bears - 1 })),
eatFish: () => set((state) => ({ fishes: state.fishes - 1 })),
})

const createFishSlice: StateCreator<
BearSlice & FishSlice,
[],
[],
FishSlice
> = (set) => ({
fishes: 0,
addFish: () => set((state) => ({ fishes: state.fishes + 1 })),
})

const useSharedStore = create<BearSlice & FishSlice>()(
temporal(
(...a) => ({
...createBearSlice(...a),
...createFishSlice(...a),
}),
{
limit: 10
}
)
)

function useTemporalStore(): TemporalState<BearSlice & FishSlice>;
function useTemporalStore<T>(
selector: (state: TemporalState<BearSlice & FishSlice>) => T
): T;
function useTemporalStore<T>(
selector: (state: TemporalState<BearSlice & FishSlice>) => T,
equality: (a: T, b: T) => boolean
): T;
function useTemporalStore<T>(
selector?: (state: TemporalState<BearSlice & FishSlice>) => T,
equality?: (a: T, b: T) => boolean
) {
return useStoreWithEqualityFn(useSharedStore.temporal, selector!, equality);
}

const UndoBar = () => {
const { undo, redo, pastStates, futureStates } = useTemporalStore(
(state) => ({
undo: state.undo,
redo: state.redo,
pastStates: state.pastStates,
futureStates: state.futureStates,
})
);

return (
<div>
past states: {JSON.stringify(pastStates)}
<br />
future states: {JSON.stringify(futureStates)}
<br />
<button onClick={() => undo()} disabled={!pastStates.length}>
undo
</button>
<button onClick={() => redo()} disabled={!futureStates.length}>
redo
</button>
</div>
);
};

const BearState = () => {
const { bears, addBear, eatFish } = useSharedStore(useShallow((state) => ({
bears: state.bears,
addBear: state.addBear,
eatFish: state.eatFish,
})));

return (
<div>
bears: {bears}
<br />
<button onClick={addBear}>Add Bear</button>
<button onClick={eatFish}>Eat Fish</button>
</div>
);
};

const FishState = () => {
const { fishes, addFish } = useSharedStore(useShallow((state) => ({
fishes: state.fishes,
addFish: state.addFish,
})));

return (
<div>
fishes: {fishes}
<br />
<button onClick={addFish}>Add Fish</button>
</div>
);
};

const App = () => {
return (
<div>
<h1>
{' '}
<span role="img" aria-label="bear">
🐻
</span>{' '}
<span role="img" aria-label="recycle">
♻️
</span>{' '}
Zundo!
</h1>
<BearState />
<FishState />
<br />
<UndoBar />
</div>
);
};

export default App;

0 comments on commit 2c2494d

Please sign in to comment.