mirror of
https://github.com/microsoft/frontend-bootcamp.git
synced 2026-01-26 14:56:42 +08:00
got add, remove, and edit actions working
This commit is contained in:
@@ -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>;
|
||||
|
||||
@@ -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))
|
||||
};
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
|
||||
48
playground/src/service/todosService.ts
Normal file
48
playground/src/service/todosService.ts
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user