got add, remove, and edit actions working

This commit is contained in:
Ken
2019-02-01 09:47:04 -08:00
parent 260b6177fe
commit 0e0ea2ef06
9 changed files with 860 additions and 108 deletions

View File

@@ -1,7 +1,12 @@
import { action, GenericActionTypes, GenericAction, GenericActionLookup } from '../redux-utils/action';
import { Dispatch } from 'redux';
import { Store } from '../store';
import * as todosService from '../service/todosService';
let counter = 0;
export const actions = {
add: (label: string) => action('add', { label }),
add: (label: string) => action('add', { id: String(counter++), label }),
remove: (id: string) => action('remove', { id }),
edit: (id: string, label: string) => action('edit', { id, label }),
complete: (id: string) => action('complete', { id }),
@@ -9,6 +14,46 @@ export const actions = {
filter: (filterTypes: string) => action('filter', { filter: filterTypes })
};
export const actionsWithService = {
add: (label: string) => {
return async (dispatch: Dispatch<TodoAction>, getState: () => Store) => {
const addAction = actions.add(label);
const id = addAction.id;
dispatch(addAction);
await todosService.add(id, getState().todos[id]);
};
},
edit: (id: string, label: string) => {
return async (dispatch: Dispatch<TodoAction>, getState: () => Store) => {
dispatch(actions.edit(id, label));
await todosService.edit(id, getState().todos[id]);
};
},
remove: (id: string) => {
return async (dispatch: Dispatch<TodoAction>, getState: () => Store) => {
dispatch(actions.remove(id));
await todosService.remove(id);
};
},
complete: (id: string) => {
return async (dispatch: Dispatch<TodoAction>, getState: () => Store) => {
dispatch(actions.complete(id));
await todosService.edit(id, getState().todos[id]);
};
},
clear: () => {
return async (dispatch: Dispatch<TodoAction>, getState: () => Store) => {
dispatch(actions.clear());
await todosService.editBulk(getState().todos);
};
}
};
export type ActionTypes = GenericActionTypes<typeof actions>;
export type TodoAction = GenericAction<typeof actions>;
export type TodoActionWithService = GenericAction<typeof actionsWithService>;
export type TodoActionLookup = GenericActionLookup<typeof actions>;

View File

@@ -1,4 +1,4 @@
import { actions, TodoAction } from '../actions';
import { actions, actionsWithService } from '../actions';
import { Store, FilterTypes } from '../store';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -11,12 +11,12 @@ export function mapStateToProps({ todos, filter }: Store) {
};
}
export function mapDispatchToProps(dispatch: Dispatch<TodoAction>) {
export function mapDispatchToProps(dispatch: any) {
return {
add: (label: string) => dispatch(actions.add(label)),
remove: (id: string) => dispatch(actions.remove(id)),
complete: (id: string) => dispatch(actions.complete(id)),
edit: (id: string, label: string) => dispatch(actions.edit(id, label)),
add: (label: string) => dispatch(actionsWithService.add(label)),
remove: (id: string) => dispatch(actionsWithService.remove(id)),
complete: (id: string) => dispatch(actionsWithService.complete(id)),
edit: (id: string, label: string) => dispatch(actionsWithService.edit(id, label)),
clear: () => dispatch(actions.clear()),
setFilter: (filter: FilterTypes) => dispatch(actions.filter(filter))
};

View File

@@ -1,18 +1,36 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import { reducer } from './reducers';
import { TodoAppContainer } from './components/TodoAppContainer';
import { initializeIcons } from '@uifabric/icons';
import thunk from 'redux-thunk';
import * as todosService from './service/todosService';
import { FilterTypes } from './store';
declare var window: any;
const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// For preloading store
initializeIcons();
ReactDOM.render(
<Provider store={store}>
<TodoAppContainer />
</Provider>,
document.getElementById('app')
);
(async () => {
const preloadStore = {
todos: await todosService.getAll(),
filter: 'all' as FilterTypes
};
const store = createStore(reducer, preloadStore, composeEnhancers(applyMiddleware(thunk)));
ReactDOM.render(
<Provider store={store}>
<TodoAppContainer />
</Provider>,
document.getElementById('app')
);
})();
// For Synchronous Case
// const store = createStore(reducer, { todos: {}, filter: 'all' }, composeEnhancers(applyMiddleware(thunk)));

View File

@@ -2,15 +2,12 @@ import { createReducer } from './createReducer';
import { Store, FilterTypes } from '../store';
import { combineReducers } from 'redux';
let counter = 0;
export const reducer = combineReducers<Store>({
todos: createReducer<Store['todos']>(
{},
{
add(draft, action) {
const id = String(counter++);
draft[id] = { label: action.label, completed: false };
draft[action.id] = { label: action.label, completed: false };
return draft;
},

View File

@@ -0,0 +1,48 @@
import { TodoItem, Store } from '../store';
const HOST = 'http://localhost:3000';
export async function add(id: string, todo: TodoItem) {
const response = await fetch(`${HOST}/todos/${id}`, {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(todo)
});
return await response.json();
}
export async function edit(id: string, todo: TodoItem) {
const response = await fetch(`${HOST}/todos/${id}`, {
method: 'put',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(todo)
});
return await response.json();
}
export async function remove(id: string) {
const response = await fetch(`${HOST}/todos/${id}`, {
method: 'delete'
});
return await response.json();
}
export async function getAll() {
const response = await fetch(`${HOST}/todos`, {
method: 'get'
});
return await response.json();
}
export async function editBulk(todos: Store['todos']) {
const response = await fetch(`${HOST}/todos`, {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(todos)
});
return await response.json();
}