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:
```js
todosDux.mutation( addTodo, description => ({next_id: id, todos}) => ({
next_id: 1 + id,
todos: [...todos, { description, id, done: false }]
}));
dux.mutation(addTodo, (state, description) => {
state.todos.unshift({ description, id: state.nextId, done: false });
state.nextId++;
});
```
## Effects

View File

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

View File

@ -2,8 +2,20 @@ import {
createStore as reduxCreateStore,
applyMiddleware,
DeepPartial,
Action,
} 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<
T_LocalState = Record<any, any>,
@ -11,6 +23,10 @@ export default class Updux<
> {
#localInitial: T_LocalState;
#localActions: T_LocalActions;
#localMutations: Record<
string,
Mutation<ActionCreator, AggregateState<T_LocalState>>
> = {};
constructor(
config: Partial<{
@ -45,4 +61,12 @@ export default class Updux<
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 u from '@yanick/updeep-remeda';
const expectType = <T>(value: T) => value;
@ -23,7 +24,7 @@ test('initial state', () => {
expect(store.getState()).toEqual(initial);
});
test.only('actions', () => {
test('actions', () => {
const addTodo = createAction('addTodo', withPayload<string>());
const todoDone = createAction('todoDone');
@ -39,3 +40,22 @@ test.only('actions', () => {
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++;
});
});