Skip to content

Commit 98e94e9

Browse files
committed
redux
1 parent 10b6666 commit 98e94e9

File tree

14 files changed

+313
-69
lines changed

14 files changed

+313
-69
lines changed

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
"name": "swppfront",
33
"version": "0.1.0",
44
"private": true,
5+
"proxy": "http://localhost:8000",
56
"dependencies": {
7+
"axios": "^0.20.0",
68
"react": "^16.9.0",
79
"react-dom": "^16.9.0",
10+
"react-redux": "^7.2.1",
811
"react-router": "^5.2.0",
912
"react-router-dom": "^5.2.0",
10-
"react-scripts": "3.1.1"
13+
"react-scripts": "3.1.1",
14+
"redux": "^4.0.5",
15+
"redux-thunk": "^2.3.0"
1116
},
1217
"scripts": {
1318
"start": "react-scripts start",

src/App.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import './App.css';
44
import TodoList from './containers/TodoList/TodoList';
55
import NewTodo from './containers/TodoList/NewTodo/NewTodo'
66
import { BrowserRouter, Route, Redirect, Switch } from 'react-router-dom'
7-
import TodoDetail from './components/TodoDetail/TodoDetail';
7+
import RealDetail from './containers/TodoList/RealDetail/RealDetail';
88

99
function App() {
1010
return (
1111
<BrowserRouter>
1212
<div className="App">
1313
<Switch>
1414
<Route path='/todos' exact render={() => <TodoList title="My TODOs!" />} />
15-
<Route path='/todos/:id' exact component={TodoDetail}/>
15+
<Route path='/todos/:id' exact component={RealDetail}/>
1616
<Route path='/new-todo' exact component={NewTodo} />
1717
<Redirect exact from='/' to='/todos' />
1818
<Route render={() => <h1>Not Found</h1>} />

src/components/Todo/Todo.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import "./Todo.css"
44
const Todo = props => {
55
return (
66
<div className='Todo'>
7-
<div className={`text ${props.done && 'done'}`} onClick={props.clicked}>
7+
<div className={`text ${props.done && 'done'}`} onClick={props.clickDetail}>
88
{props.title}
99
</div>
1010
{props.done && <div className='don-mark'>&#x2713;</div>}
11+
<button onClick={props.clickDone}>{ (props.done) ? 'Undone' : 'Done'}</button>
12+
<button onClick={props.clickDelete}>Delete</button>
1113
</div>
1214
);
1315
};

src/components/TodoDetail/TodoDetail.js

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/containers/TodoList/NewTodo/NewTodo.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import React, { Component } from 'react';
22
import { Redirect } from 'react-router-dom'
3+
34
import './NewTodo.css';
45

6+
import { connect } from 'react-redux';
7+
import * as actionCreators from '../../../store/actions/index';
8+
59
class NewTodo extends Component {
610
state = {
711
title: '',
@@ -10,11 +14,8 @@ class NewTodo extends Component {
1014
}
1115

1216
postTodoHandler = () => {
13-
const data =
14-
{ title: this.state.title, content: this.state.content };
15-
alert('Submitted\n' + data.title + '\n' + data.content);
16-
this.setState( {submitted: true} );
17-
this.props.history.push('/todos');
17+
this.props.onStoreTodo(this.state.title, this.state.content);
18+
this.setState( {submitted: true } );
1819
}
1920

2021
render() {
@@ -35,4 +36,10 @@ class NewTodo extends Component {
3536
);
3637
}
3738
};
38-
export default NewTodo;
39+
const mapDispatchToProps = dispatch => {
40+
return {
41+
onStoreTodo: (title, content) =>
42+
dispatch(actionCreators.postTodo({title: title, content: content})),
43+
};
44+
};
45+
export default connect(null, mapDispatchToProps)(NewTodo);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
.TodoDetail .row {
1+
.RealDetail .row {
22
display: flex;
33
padding: 20px;
44
height: 30px;
55
text-align: left;
66
}
77

8-
.TodoDetail .left {
8+
.RealDetail .left {
99
font-weight: bold;
1010
flex: 25%
1111
}
1212

13-
.TodoDetail .right {
13+
.RealDetail .right {
1414
flex: 75%;
1515
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React, { Component } from 'react';
2+
import { connect } from 'react-redux';
3+
import * as actionCreators from '../../../store/actions/index';
4+
5+
import './RealDetail.css';
6+
7+
class RealDetail extends Component {
8+
componentDidMount() {
9+
this.props.onGetTodo(parseInt(this.props.match.params.id));
10+
}
11+
12+
13+
render() {
14+
let content = '', title = '';
15+
if (this.props.selectedTodo) {
16+
title = this.props.selectedTodo.title;
17+
content = this.props.selectedTodo.content;
18+
}
19+
20+
return (
21+
<div className="RealDetail">
22+
<div className="row">
23+
<div className="left">
24+
Name
25+
</div>
26+
<div className="right">
27+
{title}
28+
</div>
29+
</div>
30+
<div className="row">
31+
<div className="left">
32+
Content
33+
</div>
34+
<div className="right">
35+
{content}
36+
</div>
37+
</div>
38+
</div>
39+
);
40+
}
41+
42+
}
43+
44+
const mapStateToProps = state => {
45+
return {
46+
selectedTodo: state.td.selectedTodo
47+
}
48+
}
49+
50+
const mapDispatchToProps = dispatch => {
51+
return {
52+
onGetTodo: (id) => dispatch(actionCreators.getTodo(id)),
53+
}
54+
}
55+
56+
export default connect(mapStateToProps, mapDispatchToProps)(RealDetail);
Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,64 @@
11
import React, {Component} from 'react';
2+
23
import Todo from '../../components/Todo/Todo';
3-
import TodoDetail from '../../components/TodoDetail/TodoDetail';
4+
45
import { NavLink } from 'react-router-dom';
5-
import NewTodo from './NewTodo/NewTodo';
6+
67
import "./TodoList.css"
78

9+
import { connect } from 'react-redux';
10+
import * as actionTypes from '../../store/actions/actionTypes';
11+
import * as actionCreators from '../../store/actions/index';
12+
13+
import { withRouter } from 'react-router';
14+
815
class TodoList extends Component {
9-
state = {
10-
todos: [
11-
{id: 1, title: 'SWPP', content: 'take swpp class', done: true},
12-
{id: 2, title: 'Movie', content: 'watch movie', done: false},
13-
{id: 3, title: 'Dinner', content: 'eat dinner', done: false},
14-
],
15-
selectedTodo: null,
16+
componentDidMount() {
17+
this.props.onGetAll();
1618
}
1719

18-
clickTodoHandler = td => {
19-
if (this.state.selectedTodo === td) {
20-
this.setState({selectedTodo: null});
21-
} else {
22-
this.setState({selectedTodo: td});
23-
}
20+
clickTodoHandler = (td) => {
21+
this.props.history.push('/todos/' + td.id);
2422
}
2523

2624
render() {
27-
const todos = this.state.todos.map((td) => {
28-
return ( <Todo key={td.id} title={td.title}
29-
done={td.done} clicked={() => this.clickTodoHandler(td)}/> );
25+
const todos = this.props.storedTodos.map((td) => {
26+
return (
27+
<Todo
28+
key={td.id}
29+
title={td.title}
30+
done={td.done}
31+
clickDetail={() => this.clickTodoHandler(td)}
32+
clickDone={() => this.props.onToggleTodo(td.id)}
33+
clickDelete={() => this.props.onDeleteTodo(td.id)} />
34+
);
3035
});
31-
let todoDetail = null;
32-
if (this.state.selectedTodo) {
33-
todoDetail = <TodoDetail title={this.state.selectedTodo.title}
34-
content={this.state.selectedTodo.content} />
35-
}
36+
37+
let todo = null;
3638
return (
3739
<div className='TodoList'>
3840
<div className='title'>{this.props.title}</div>
3941
<div className='todos'>{todos}</div>
40-
{todoDetail}
42+
{todo}
4143
<NavLink to='new-todo' exact>New Todo</NavLink>
4244
</div>
4345
);
4446
}
47+
}
4548

46-
47-
48-
49+
const mapStateToProps = state => {
50+
return {
51+
storedTodos: state.td.todos,
52+
selectedTodo: state.td.selectedTodo,
53+
};
4954
}
50-
export default TodoList;
55+
56+
const mapDispatchToProps = dispatch => {
57+
return {
58+
onToggleTodo: (id) => dispatch(actionCreators.toggleTodo(id)),
59+
onDeleteTodo: (id) => dispatch(actionCreators.deleteTodo(id)),
60+
onGetAll: () => dispatch(actionCreators.getTodos()),
61+
onGetTodo: (id) => dispatch(actionCreators.getTodo(id)),
62+
};
63+
};
64+
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(TodoList));

src/index.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,25 @@ import './index.css';
44
import App from './App';
55
import * as serviceWorker from './serviceWorker';
66

7-
ReactDOM.render(<App />, document.getElementById('root'));
7+
import { Provider } from 'react-redux';
8+
9+
import { createStore, combineReducers, applyMiddleware } from 'redux';
10+
import thunk from 'redux-thunk';
11+
12+
import todoReducer from './store/reducers/todo';
13+
14+
15+
const rootReducer = combineReducers({
16+
td: todoReducer,
17+
});
18+
19+
const store = createStore(rootReducer, applyMiddleware(thunk));
20+
21+
ReactDOM.render(
22+
<Provider store={store}>
23+
<App />
24+
</Provider>,
25+
document.getElementById('root'));
826

927
// If you want your app to work offline and load faster, you can change
1028
// unregister() to register() below. Note this comes with some pitfalls.

src/store/actions/actionTypes.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const GET_ALL = 'GET_ALL';
2+
export const GET_TODO = 'GET_TODO';
3+
export const TOGGLE_DONE = 'TOGGLE_DONE';
4+
export const DELETE_TODO = 'DELETE_TODO';
5+
export const ADD_TODO = 'ADD_TODO';
6+

0 commit comments

Comments
 (0)