Skip to content

Commit 932838a

Browse files
committed
bootstrapping
1 parent 7618044 commit 932838a

File tree

1 file changed

+15
-296
lines changed

1 file changed

+15
-296
lines changed

src/index.js

Lines changed: 15 additions & 296 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,22 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3-
import { applyMiddleware, combineReducers, createStore } from 'redux';
4-
import { Provider, connect } from 'react-redux';
5-
import { createLogger } from 'redux-logger';
6-
import createSagaMiddleware, { delay } from 'redux-saga';
7-
import { put, takeEvery } from 'redux-saga/effects';
8-
import { schema, normalize } from 'normalizr';
9-
import uuid from 'uuid/v4';
3+
import { combineReducers, createStore } from 'redux';
104
import './index.css';
115

12-
// filters
13-
14-
const VISIBILITY_FILTERS = {
15-
SHOW_COMPLETED: item => item.completed,
16-
SHOW_INCOMPLETED: item => !item.completed,
17-
SHOW_ALL: item => true,
18-
};
19-
20-
// schemas
21-
22-
const todoSchema = new schema.Entity('todo');
23-
246
// action types
257

268
const TODO_ADD = 'TODO_ADD';
279
const TODO_TOGGLE = 'TODO_TOGGLE';
2810
const FILTER_SET = 'FILTER_SET';
29-
const NOTIFICATION_HIDE = 'NOTIFICATION_HIDE';
30-
const TODO_ADD_WITH_NOTIFICATION = 'TODO_ADD_WITH_NOTIFICATION';
3111

3212
// reducers
3313

3414
const todos = [
35-
{ id: uuid(), name: 'Hands On: Snake with Local State' },
36-
{ id: uuid(), name: 'Challenge: Snake with Higher Order Components' },
37-
{ id: uuid(), name: 'Hands On: Redux Standalone with advanced Actions' },
38-
{ id: uuid(), name: 'Hands On: Redux Standalone with advanced Reducers' },
39-
{ id: uuid(), name: 'Hands On: Bootstrap App with Redux' },
40-
{ id: uuid(), name: 'Hands On: Naive Todo with React and Redux' },
41-
{ id: uuid(), name: 'Hands On: Sophisticated Todo with React and Redux' },
42-
{ id: uuid(), name: 'Hands On: Connecting State Everywhere' },
43-
{ id: uuid(), name: 'Challenge: Snake with React and Redux' },
44-
{ id: uuid(), name: 'Hands On: Todo with advanced Redux' },
45-
{ id: uuid(), name: 'Hands On: Todo with more Features' },
46-
{ id: uuid(), name: 'Challenge: Snake with Redux' },
47-
{ id: uuid(), name: 'Hands On: Todo with Notifications' },
48-
{ id: uuid(), name: 'Challenge: Snake with Redux and Async Actions' },
49-
{ id: uuid(), name: 'Hands On: Hacker News with Redux' },
50-
{ id: uuid(), name: 'Challenge: Hacker News with beyond Redux' },
51-
{ id: uuid(), name: 'Challenge: Hacker News with beyond Redux' },
52-
{ id: uuid(), name: 'Hands On: Snake with MobX' },
53-
{ id: uuid(), name: 'Hands On: Todo App with MobX' },
54-
{ id: uuid(), name: 'Challenge: Hacker News App with MobX' },
55-
{ id: uuid(), name: 'Challenge: Consuming a GrapQL API with Relay' },
15+
{ id: '0', name: 'learn redux' },
16+
{ id: '1', name: 'learn mobx' },
5617
];
5718

58-
const normalizedTodos = normalize(todos, [todoSchema]);
59-
60-
const initialTodoState = {
61-
entities: normalizedTodos.entities.todo,
62-
ids: normalizedTodos.result,
63-
};
64-
65-
function todoReducer(state = initialTodoState, action) {
19+
function todoReducer(state = todos, action) {
6620
switch(action.type) {
6721
case TODO_ADD : {
6822
return applyAddTodo(state, action);
@@ -75,18 +29,16 @@ function todoReducer(state = initialTodoState, action) {
7529
}
7630

7731
function applyAddTodo(state, action) {
78-
const todo = { ...action.todo, completed: false };
79-
const entities = { ...state.entities, [todo.id]: todo };
80-
const ids = [ ...state.ids, action.todo.id ];
81-
return { ...state, entities, ids };
32+
const todo = Object.assign({}, action.todo, { completed: false });
33+
return state.concat(todo);
8234
}
8335

8436
function applyToggleTodo(state, action) {
85-
const id = action.todo.id;
86-
const todo = state.entities[id];
87-
const toggledTodo = { ...todo, completed: !todo.completed };
88-
const entities = { ...state.entities, [id]: toggledTodo };
89-
return { ...state, entities };
37+
return state.map(todo =>
38+
todo.id === action.todo.id
39+
? Object.assign({}, todo, { completed: !todo.completed })
40+
: todo
41+
);
9042
}
9143

9244
function filterReducer(state = 'SHOW_ALL', action) {
@@ -102,47 +54,8 @@ function applySetFilter(state, action) {
10254
return action.filter;
10355
}
10456

105-
function notificationReducer(state = {}, action) {
106-
switch(action.type) {
107-
case TODO_ADD : {
108-
return applySetNotifyAboutAddTodo(state, action);
109-
}
110-
case NOTIFICATION_HIDE : {
111-
return applyRemoveNotification(state, action);
112-
}
113-
default : return state;
114-
}
115-
}
116-
117-
function applySetNotifyAboutAddTodo(state, action) {
118-
const { name, id } = action.todo;
119-
return { ...state, [id]: 'Todo Created: ' + name };
120-
}
121-
122-
function applyRemoveNotification(state, action) {
123-
const {
124-
[action.id]: notificationToRemove,
125-
...restNotifications,
126-
} = state;
127-
return restNotifications;
128-
}
129-
13057
// action creators
13158

132-
function doAddTodoWithNotification(id, name) {
133-
return {
134-
type: TODO_ADD_WITH_NOTIFICATION,
135-
todo: { id, name },
136-
};
137-
}
138-
139-
function doHideNotification(id) {
140-
return {
141-
type: NOTIFICATION_HIDE,
142-
id
143-
};
144-
}
145-
14659
function doAddTodo(id, name) {
14760
return {
14861
type: TODO_ADD,
@@ -164,213 +77,19 @@ function doSetFilter(filter) {
16477
};
16578
}
16679

167-
// selectors
168-
169-
function getTodosAsIds(state) {
170-
return state.todoState.ids
171-
.map(id => state.todoState.entities[id])
172-
.filter(VISIBILITY_FILTERS[state.filterState])
173-
.map(todo => todo.id);
174-
}
175-
176-
function getTodo(state, todoId) {
177-
return state.todoState.entities[todoId];
178-
}
179-
180-
function getNotifications(state) {
181-
return getArrayOfObject(state.notificationState);
182-
}
183-
184-
function getArrayOfObject(object) {
185-
return Object.keys(object).map(key => object[key]);
186-
}
187-
188-
// sagas
189-
190-
function* watchAddTodoWithNotification() {
191-
yield takeEvery(TODO_ADD_WITH_NOTIFICATION, handleAddTodoWithNotification);
192-
}
193-
194-
function* handleAddTodoWithNotification(action) {
195-
const { todo } = action;
196-
const { id, name } = todo;
197-
yield put(doAddTodo(id, name));
198-
yield delay(5000);
199-
yield put(doHideNotification(id));
200-
}
201-
20280
// store
20381

20482
const rootReducer = combineReducers({
20583
todoState: todoReducer,
20684
filterState: filterReducer,
207-
notificationState: notificationReducer,
20885
});
20986

210-
const logger = createLogger();
211-
const saga = createSagaMiddleware();
87+
const store = createStore(rootReducer);
21288

213-
const store = createStore(
214-
rootReducer,
215-
undefined,
216-
applyMiddleware(saga, logger)
217-
);
218-
219-
saga.run(watchAddTodoWithNotification);
220-
221-
// components
89+
// view layer
22290

22391
function TodoApp() {
224-
return (
225-
<div>
226-
<ConnectedFilter />
227-
<ConnectedTodoCreate />
228-
<ConnectedTodoList />
229-
<ConnectedNotifications />
230-
</div>
231-
);
232-
}
233-
234-
function Notifications({ notifications }) {
235-
return (
236-
<div>
237-
{notifications.map(note => <div key={note}>{note}</div>)}
238-
</div>
239-
);
240-
}
241-
242-
function Filter({ onSetFilter }) {
243-
return (
244-
<div>
245-
Show
246-
<button
247-
type="text"
248-
onClick={() => onSetFilter('SHOW_ALL')}>
249-
All</button>
250-
<button
251-
type="text"
252-
onClick={() => onSetFilter('SHOW_COMPLETED')}>
253-
Completed</button>
254-
<button
255-
type="text"
256-
onClick={() => onSetFilter('SHOW_INCOMPLETED')}>
257-
Incompleted</button>
258-
</div>
259-
);
260-
}
261-
262-
class TodoCreate extends React.Component {
263-
constructor(props) {
264-
super(props);
265-
266-
this.state = {
267-
value: '',
268-
};
269-
270-
this.onCreateTodo = this.onCreateTodo.bind(this);
271-
this.onChangeName = this.onChangeName.bind(this);
272-
}
273-
274-
onChangeName(event) {
275-
this.setState({ value: event.target.value });
276-
}
277-
278-
onCreateTodo(event) {
279-
this.props.onAddTodo(this.state.value);
280-
this.setState({ value: '' });
281-
event.preventDefault();
282-
}
283-
284-
render() {
285-
return (
286-
<div>
287-
<form onSubmit={this.onCreateTodo}>
288-
<input
289-
type="text"
290-
placeholder="Add Todo..."
291-
value={this.state.value}
292-
onChange={this.onChangeName}
293-
/>
294-
<button type="submit">Add</button>
295-
</form>
296-
</div>
297-
);
298-
}
299-
}
300-
301-
function TodoList({ todosAsIds }) {
302-
return (
303-
<div>
304-
{todosAsIds.map(todoId => <ConnectedTodoItem
305-
key={todoId}
306-
todoId={todoId}
307-
/>)}
308-
</div>
309-
);
92+
return <div>Todo App</div>;
31093
}
31194

312-
function TodoItem({ todo, onToggleTodo }) {
313-
const { name, id, completed } = todo;
314-
return (
315-
<div>
316-
{name}
317-
<button
318-
type="button"
319-
onClick={() => onToggleTodo(id)}
320-
>
321-
{completed ? "Incomplete" : "Complete"}
322-
</button>
323-
</div>
324-
);
325-
}
326-
327-
// Connecting React and Redux
328-
329-
function mapStateToPropsList(state) {
330-
return {
331-
todosAsIds: getTodosAsIds(state),
332-
};
333-
}
334-
335-
function mapStateToPropsItem(state, props) {
336-
return {
337-
todo: getTodo(state, props.todoId),
338-
};
339-
}
340-
341-
function mapDispatchToPropsItem(dispatch) {
342-
return {
343-
onToggleTodo: id => dispatch(doToggleTodo(id)),
344-
};
345-
}
346-
347-
function mapDispatchToPropsCreate(dispatch) {
348-
return {
349-
onAddTodo: name => dispatch(doAddTodoWithNotification(uuid(), name)),
350-
};
351-
}
352-
353-
function mapDispatchToPropsFilter(dispatch) {
354-
return {
355-
onSetFilter: filterType => dispatch(doSetFilter(filterType)),
356-
};
357-
}
358-
359-
function mapStateToPropsNotifications(state, props) {
360-
return {
361-
notifications: getNotifications(state),
362-
};
363-
}
364-
365-
const ConnectedTodoList = connect(mapStateToPropsList)(TodoList);
366-
const ConnectedTodoItem = connect(mapStateToPropsItem, mapDispatchToPropsItem)(TodoItem);
367-
const ConnectedTodoCreate = connect(null, mapDispatchToPropsCreate)(TodoCreate);
368-
const ConnectedFilter = connect(null, mapDispatchToPropsFilter)(Filter);
369-
const ConnectedNotifications = connect(mapStateToPropsNotifications)(Notifications);
370-
371-
ReactDOM.render(
372-
<Provider store={store}>
373-
<TodoApp />
374-
</Provider>,
375-
document.getElementById('root')
376-
);
95+
ReactDOM.render(<TodoApp />, document.getElementById('root'));

0 commit comments

Comments
 (0)