This commit is contained in:
Yanick Champoux 2023-03-06 10:09:39 -05:00
parent 29d3d9a2aa
commit 80d18703c4
4 changed files with 51 additions and 6 deletions

View File

@ -72,10 +72,10 @@ Mutations are the reducing functions associated to actions. They
are defined via the `mutation` method: are defined via the `mutation` method:
```js ```js
todosDux.mutation( addTodo, description => ({next_id: id, todos}) => ({ dux.mutation(addTodo, (state, description) => {
next_id: 1 + id, state.todos.unshift({ description, id: state.nextId, done: false });
todos: [...todos, { description, id, done: false }] state.nextId++;
})); });
``` ```
## Effects ## Effects

View File

@ -1,6 +1,7 @@
{ {
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@yanick/updeep-remeda": "^2.1.0",
"immer": "^9.0.15", "immer": "^9.0.15",
"json-schema-shorthand": "^2.0.0", "json-schema-shorthand": "^2.0.0",
"redux": "^4.2.0", "redux": "^4.2.0",

View File

@ -2,8 +2,20 @@ import {
createStore as reduxCreateStore, createStore as reduxCreateStore,
applyMiddleware, applyMiddleware,
DeepPartial, DeepPartial,
Action,
} from 'redux'; } from 'redux';
import { configureStore, Reducer } from '@reduxjs/toolkit'; import { configureStore, Reducer, createAction } from '@reduxjs/toolkit';
import { withPayload } from './actions';
type ActionCreator = ReturnType<typeof createAction>;
type AggregateState<L> = L;
type Mutation<A extends ActionCreator = ActionCreator, S = any> = (
state: S,
payload: ReturnType<A>['payload'],
action: ReturnType<A>,
) => S | void;
export default class Updux< export default class Updux<
T_LocalState = Record<any, any>, T_LocalState = Record<any, any>,
@ -11,6 +23,10 @@ export default class Updux<
> { > {
#localInitial: T_LocalState; #localInitial: T_LocalState;
#localActions: T_LocalActions; #localActions: T_LocalActions;
#localMutations: Record<
string,
Mutation<ActionCreator, AggregateState<T_LocalState>>
> = {};
constructor( constructor(
config: Partial<{ config: Partial<{
@ -45,4 +61,12 @@ export default class Updux<
return store; return store;
} }
// TODO force the actionCreator to be one of the actions?
mutation<A extends ActionCreator>(
actionCreator: A,
mutation: Mutation<A, AggregateState<T_LocalState>>,
) {
this.#localMutations[actionCreator.type] = mutation;
}
} }

View File

@ -1,4 +1,5 @@
import Updux, { createAction, withPayload } from './index.js'; import Updux, { createAction, withPayload } from './index.js';
import u from '@yanick/updeep-remeda';
const expectType = <T>(value: T) => value; const expectType = <T>(value: T) => value;
@ -23,7 +24,7 @@ test('initial state', () => {
expect(store.getState()).toEqual(initial); expect(store.getState()).toEqual(initial);
}); });
test.only('actions', () => { test('actions', () => {
const addTodo = createAction('addTodo', withPayload<string>()); const addTodo = createAction('addTodo', withPayload<string>());
const todoDone = createAction('todoDone'); const todoDone = createAction('todoDone');
@ -39,3 +40,22 @@ test.only('actions', () => {
payload: 'write tutorial', payload: 'write tutorial',
}); });
}); });
test('mutation', () => {
const addTodo = createAction('addTodo', withPayload<string>());
type Todo = {
description: string;
id: number;
done: boolean;
};
const dux = new Updux({
initial: { nextId: 0, todos: [] as Todo[] },
});
dux.mutation(addTodo, (state, description) => {
state.todos.unshift({ description, id: state.nextId, done: false });
state.nextId++;
});
});