From e24962a2e3fafbb233650ccf3060e2f87b467cb9 Mon Sep 17 00:00:00 2001 From: gina7484 <46814676+gina7484@users.noreply.github.com> Date: Fri, 25 Sep 2020 19:21:18 +0900 Subject: [PATCH 1/5] first commit --- package.json | 4 +- src/containers/TodoList/NewTodo/NewTodo.js | 20 +++++++-- src/containers/TodoList/TodoList.js | 23 ++++++++++- src/index.js | 20 ++++++++- src/store/actions/actionTypes.js | 5 +++ src/store/reducers/todo.js | 47 +++++++++++++++++++++ yarn.lock | 48 ++++++++++++++++++++++ 7 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 src/store/actions/actionTypes.js create mode 100644 src/store/reducers/todo.js diff --git a/package.json b/package.json index 4488cb3..225cbeb 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,11 @@ "dependencies": { "react": "^16.9.0", "react-dom": "^16.9.0", + "react-redux": "^7.2.1", "react-router": "^5.0.1", "react-router-dom": "^5.0.1", - "react-scripts": "3.1.1" + "react-scripts": "3.1.1", + "redux": "^4.0.5" }, "scripts": { "start": "react-scripts start", diff --git a/src/containers/TodoList/NewTodo/NewTodo.js b/src/containers/TodoList/NewTodo/NewTodo.js index 59e7930..774b28b 100644 --- a/src/containers/TodoList/NewTodo/NewTodo.js +++ b/src/containers/TodoList/NewTodo/NewTodo.js @@ -1,6 +1,9 @@ import React, { Component } from 'react'; +import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; +import * as actionTypes from '../../../store/actions/actionTypes'; +//all of them are inside actionTypes import './NewTodo.css'; @@ -14,7 +17,8 @@ class NewTodo extends Component { postTodoHandler = () => { const data = { title: this.state.title, content: this.state.content } - alert('submitted' + data.title); + this.props.onStoreTodo(this.state.title,this.state.content); + alert('submitted' + data.title); // this.props.history.push('/todos'); this.props.history.goBack(); this.setState({ submitted: true }); @@ -36,7 +40,7 @@ class NewTodo extends Component { > @@ -45,4 +49,14 @@ class NewTodo extends Component { } } -export default NewTodo; \ No newline at end of file +const mapDispatchToProps = dispatch => { + return { + onStoreTodo: (title, content) => + dispatch({ + type: actionTypes.ADD_TODO, + title: title, + content: content, }), + } +}; + +export default connect(null, mapDispatchToProps)(NewTodo); diff --git a/src/containers/TodoList/TodoList.js b/src/containers/TodoList/TodoList.js index 6cb72c1..afccf0b 100644 --- a/src/containers/TodoList/TodoList.js +++ b/src/containers/TodoList/TodoList.js @@ -1,4 +1,5 @@ import React, { Component } from 'react'; +import { connect } from 'react-redux'; import Todo from '../../components/Todo/Todo'; import TodoDetail from '../../components/TodoDetail/TodoDetail'; @@ -26,7 +27,7 @@ class TodoList extends Component { } render() { - const todos = this.state.todos.map(td => { + const todos = this.props.storedTodos.map(td => { return ( { //global state + return { + storedTodos: state.td.todos, + //td acts like a namespace + }; +} +/* +const mapDispatchToProps = dispatch => { + return { + onToggleTodo: (id) => + dispatch({ type: actionTypes.TOGGLE_DONE, targetID: id }), + onDeleteTodo: (id) => + dispatch({ type: actionTypes.DELETE_TODO, targetID: id }), + } +} +*/ + +export default connect(mapStateToProps, null)(TodoList); \ No newline at end of file diff --git a/src/index.js b/src/index.js index 87d1be5..ae0523a 100644 --- a/src/index.js +++ b/src/index.js @@ -3,8 +3,26 @@ import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; +import { Provider } from 'react-redux'; -ReactDOM.render(, document.getElementById('root')); +import { createStore, combineReducers } from 'redux'; +import todoReducer from './store/reducers/todo'; + +const rootReducer = combineReducers({ + td: todoReducer, //td: used as name space + }); + + +const store = createStore(rootReducer); + + + +ReactDOM.render( + + + , + document.getElementById('root') +); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. diff --git a/src/store/actions/actionTypes.js b/src/store/actions/actionTypes.js new file mode 100644 index 0000000..cdeee47 --- /dev/null +++ b/src/store/actions/actionTypes.js @@ -0,0 +1,5 @@ +export const GET_ALL = 'GET_ALL'; +export const ADD_TODO = 'ADD_TODO'; +export const TOGGLE_DONE = 'TOGGLE_DONE'; +export const DELETE_TODO = 'DELETE_TODO'; +export const GET_TODO = 'GET_TODO'; \ No newline at end of file diff --git a/src/store/reducers/todo.js b/src/store/reducers/todo.js new file mode 100644 index 0000000..07e9c17 --- /dev/null +++ b/src/store/reducers/todo.js @@ -0,0 +1,47 @@ +import * as actionTypes from '../actions/actionTypes'; + +const initialState = { + todos: [ + { id: 1, title: 'SWPP', content: 'take swpp class', done: true }, + { id: 2, title: 'Movie', content: 'watch movie', done: false }, + { id: 3, title: 'Dinner', content: 'eat dinner', done: false } + ], + selectedTodo: null, +}; + +const reducer = (state = initialState, action) => { + switch (action.type) { + case actionTypes.ADD_TODO: + const newTodo = { + id: state.todos.length + 1, + title: action.title, content: action.content, + done: false + }; + // state.todos.push(newTodo);//Bad!! + return { ...state, todos: [...state.todos,newTodo] }; + // concat has the same meaning + case actionTypes.DELETE_TODO: + const deletedTodos = state.todos.filter((todo) => { + return todo.id !== action.targetID; + }); + return { ...state, todos: deletedTodos }; + case actionTypes.TOGGLE_DONE: + const modified = state.todos.map((todo) => { + if (todo.id === action.targetID) { + return { ...todo, done: !todo.done }; + } else { + return { ...todo }; + } + }); + return { ...state, todos: modified }; + case actionTypes.GET_TODO: + const target = { ...state.todos[action.targetID - 1] }; + return { ...state, selectedTodo: target }; + default: + break; + } + return state; +}; + +export default reducer; +//you can import this name as any name you want in other js files. (cuz it's exported as default) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 54cccc1..08f6b55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -770,6 +770,13 @@ dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.5.5": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" @@ -4429,6 +4436,13 @@ hoist-non-react-statics@^3.1.0: dependencies: react-is "^16.7.0" +hoist-non-react-statics@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.4" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" @@ -7944,6 +7958,22 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== +react-is@^16.9.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-redux@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985" + integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg== + dependencies: + "@babel/runtime" "^7.5.5" + hoist-non-react-statics "^3.3.0" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^16.9.0" + react-router-dom@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be" @@ -8122,6 +8152,14 @@ recursive-readdir@2.2.2: dependencies: minimatch "3.0.4" +redux@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -8144,6 +8182,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + regenerator-transform@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" @@ -9115,6 +9158,11 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" From bf152266cb2c2f8d6814b802411a953322f5a30f Mon Sep 17 00:00:00 2001 From: gina7484 <46814676+gina7484@users.noreply.github.com> Date: Fri, 25 Sep 2020 19:40:14 +0900 Subject: [PATCH 2/5] second commit --- src/components/Todo/Todo.js | 4 +++- src/containers/TodoList/TodoList.js | 24 +++++++++++------------- src/store/reducers/todo.js | 18 +++++++++--------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/components/Todo/Todo.js b/src/components/Todo/Todo.js index 9c80927..22b5e28 100644 --- a/src/components/Todo/Todo.js +++ b/src/components/Todo/Todo.js @@ -8,10 +8,12 @@ const Todo = (props) => {
+ onClick={props.clickDetail}> {props.title}
{props.done &&
} + +
); }; diff --git a/src/containers/TodoList/TodoList.js b/src/containers/TodoList/TodoList.js index afccf0b..d1a3535 100644 --- a/src/containers/TodoList/TodoList.js +++ b/src/containers/TodoList/TodoList.js @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; - +import {withRouter} from 'react-router'; import Todo from '../../components/Todo/Todo'; import TodoDetail from '../../components/TodoDetail/TodoDetail'; +import * as actionTypes from '../../store/actions/actionTypes'; import { NavLink } from 'react-router-dom'; @@ -19,11 +20,7 @@ class TodoList extends Component { } clickTodoHandler = (td) => { - if (this.state.selectedTodo === td) { - this.setState({ ...this.state, selectedTodo: null }); - } else { - this.setState({ ...this.state, selectedTodo: td }); - } + this.props.history.push(`/todos/${td.id}`) } render() { @@ -34,6 +31,9 @@ class TodoList extends Component { title={td.title} done={td.done} clicked={() => this.clickTodoHandler(td)} + clickDetail={() => this.clickTodoHandler(td)} + clickDone={() => this.props.onToggleTodo(td.id)} + clickDelete={() => this.props.onDeleteTodo(td.id)} /> ); }); @@ -67,15 +67,13 @@ const mapStateToProps = state => { //global state //td acts like a namespace }; } -/* + const mapDispatchToProps = dispatch => { return { - onToggleTodo: (id) => - dispatch({ type: actionTypes.TOGGLE_DONE, targetID: id }), - onDeleteTodo: (id) => - dispatch({ type: actionTypes.DELETE_TODO, targetID: id }), + onToggleTodo: (id) => dispatch({ type: actionTypes.TOGGLE_DONE, targetID: id }), + onDeleteTodo: (id) => dispatch({ type: actionTypes.DELETE_TODO, targetID: id }), } } -*/ -export default connect(mapStateToProps, null)(TodoList); \ No newline at end of file + +export default connect(mapStateToProps, mapDispatchToProps)(withRouter(TodoList)); \ No newline at end of file diff --git a/src/store/reducers/todo.js b/src/store/reducers/todo.js index 07e9c17..e592e88 100644 --- a/src/store/reducers/todo.js +++ b/src/store/reducers/todo.js @@ -20,20 +20,20 @@ const reducer = (state = initialState, action) => { // state.todos.push(newTodo);//Bad!! return { ...state, todos: [...state.todos,newTodo] }; // concat has the same meaning - case actionTypes.DELETE_TODO: - const deletedTodos = state.todos.filter((todo) => { - return todo.id !== action.targetID; - }); - return { ...state, todos: deletedTodos }; case actionTypes.TOGGLE_DONE: - const modified = state.todos.map((todo) => { - if (todo.id === action.targetID) { - return { ...todo, done: !todo.done }; + const modified = state.todos.map((td) => { + if (td.id === action.targetID) { + return { ...td, done: !td.done }; } else { - return { ...todo }; + return { ...td }; } }); return { ...state, todos: modified }; + case actionTypes.DELETE_TODO: + const deletedTodos = state.todos.filter((todo) => { + return todo.id !== action.targetID; + }); + return { ...state, todos: deletedTodos }; case actionTypes.GET_TODO: const target = { ...state.todos[action.targetID - 1] }; return { ...state, selectedTodo: target }; From 664a4181a817e280792799fe99d4f76f117b0e83 Mon Sep 17 00:00:00 2001 From: gina7484 <46814676+gina7484@users.noreply.github.com> Date: Fri, 25 Sep 2020 20:12:36 +0900 Subject: [PATCH 3/5] third commit --- src/containers/TodoList/NewTodo/NewTodo.js | 14 +-- .../TodoList/RealDetail/RealDetail.js | 30 +++++- src/containers/TodoList/TodoList.js | 92 ++++++++++++++++++- src/index.js | 5 +- src/store/reducers/todo.js | 5 +- 5 files changed, 127 insertions(+), 19 deletions(-) diff --git a/src/containers/TodoList/NewTodo/NewTodo.js b/src/containers/TodoList/NewTodo/NewTodo.js index 774b28b..4ac88dc 100644 --- a/src/containers/TodoList/NewTodo/NewTodo.js +++ b/src/containers/TodoList/NewTodo/NewTodo.js @@ -11,24 +11,14 @@ class NewTodo extends Component { state = { title: '', content: '', - submitted: false } postTodoHandler = () => { - const data = - { title: this.state.title, content: this.state.content } - this.props.onStoreTodo(this.state.title,this.state.content); - alert('submitted' + data.title); - // this.props.history.push('/todos'); - this.props.history.goBack(); - this.setState({ submitted: true }); + this.props.onStoreTodo(this.state.title, this.state.content); + this.props.history.push('/todos'); } render() { - let redirect = null; - if (this.state.submitted) { - redirect = - } return (

Add a New Todo!

diff --git a/src/containers/TodoList/RealDetail/RealDetail.js b/src/containers/TodoList/RealDetail/RealDetail.js index 89500a3..b3273fd 100644 --- a/src/containers/TodoList/RealDetail/RealDetail.js +++ b/src/containers/TodoList/RealDetail/RealDetail.js @@ -2,8 +2,21 @@ import React, { Component } from 'react'; import './RealDetail.css'; +import { connect } from 'react-redux'; +import * as actionTypes from '../../../store/actions/actionTypes'; + class RealDetail extends Component { + + componentDidMount() { + this.props.onGetTodo(parseInt(this.props.match.params.id)); + } + render() { + let content = '', title=''; + if (this.props.selectedTodo) { + title = this.props.selectedTodo.title; + content = this.props.selectedTodo.content; + } return (
@@ -11,6 +24,7 @@ class RealDetail extends Component { Name:
+ {title}
@@ -18,6 +32,7 @@ class RealDetail extends Component { Content:
+ {content}
@@ -25,4 +40,17 @@ class RealDetail extends Component { } }; -export default RealDetail; \ No newline at end of file +const mapStateToProps = state => { + return { + selectedTodo: state.td.selectedTodo, + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onGetTodo: id => + dispatch({ type: actionTypes.GET_TODO, targetID: id }), + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(RealDetail); diff --git a/src/containers/TodoList/TodoList.js b/src/containers/TodoList/TodoList.js index d1a3535..5319cfa 100644 --- a/src/containers/TodoList/TodoList.js +++ b/src/containers/TodoList/TodoList.js @@ -1,3 +1,85 @@ + +import React, { Component } from 'react'; + +import Todo from '../../components/Todo/Todo'; +import TodoDetail from '../../components/TodoDetail/TodoDetail'; + +import { NavLink } from 'react-router-dom'; + +import './TodoList.css'; + +import { connect } from 'react-redux'; +import { withRouter } from 'react-router'; +import * as actionTypes from '../../store/actions/actionTypes'; + +class TodoList extends Component { + state = { + todos: [ + { id: 1, title: 'SWPP', content: 'take swpp class', done: true }, + { id: 2, title: 'Movie', content: 'watch movie', done: false }, + { id: 3, title: 'Dinner', content: 'eat dinner', done: false } + ], + selectedTodo: null, + } + + clickTodoHandler = (td) => { + this.props.history.push(this.props.match.url + '/' + td.id); + } + + render() { + const todos = this.props.storedTodos.map(td => { + return ( + this.clickTodoHandler(td)} + clickDone={() => this.props.onToggleTodo(td.id)} + clickDelete={() => this.props.onDeleteTodo(td.id)} + /> + ); + }); + + let todo = null; + if (this.state.selectedTodo) { + todo = + } + return ( +
+
+ {this.props.title} +
+
+ {todos} +
+ {todo} + New Todo +
+ ) + } +} + +const mapStateToProps = state => { + return { + storedTodos: state.td.todos, + }; +} + +const mapDispatchToProps = dispatch => { + return { + onToggleTodo: (id) => + dispatch({ type: actionTypes.TOGGLE_DONE, targetID: id }), + onDeleteTodo: (id) => + dispatch({ type: actionTypes.DELETE_TODO, targetID: id }), + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(withRouter(TodoList)); + +/* import React, { Component } from 'react'; import { connect } from 'react-redux'; import {withRouter} from 'react-router'; @@ -39,10 +121,10 @@ class TodoList extends Component { }); let todo = null; - if (this.state.selectedTodo) { + if (this.props.selectedTodo) { todo = } return ( @@ -64,6 +146,7 @@ class TodoList extends Component { const mapStateToProps = state => { //global state return { storedTodos: state.td.todos, + selectedTodo: state.td.selectedTodo, //td acts like a namespace }; } @@ -76,4 +159,5 @@ const mapDispatchToProps = dispatch => { } -export default connect(mapStateToProps, mapDispatchToProps)(withRouter(TodoList)); \ No newline at end of file +export default connect(mapStateToProps, mapDispatchToProps)(withRouter(TodoList)); +*/ \ No newline at end of file diff --git a/src/index.js b/src/index.js index ae0523a..00dd1c5 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,10 @@ import App from './App'; import * as serviceWorker from './serviceWorker'; import { Provider } from 'react-redux'; -import { createStore, combineReducers } from 'redux'; +import { createStore, combineReducers, applyMiddleware, compose } from 'redux'; +//import thunk from 'redux-thunk'; +//import { connectRouter, routerMiddleware } from 'connected-react-router'; +import { createBrowserHistory } from 'history'; import todoReducer from './store/reducers/todo'; const rootReducer = combineReducers({ diff --git a/src/store/reducers/todo.js b/src/store/reducers/todo.js index e592e88..791ea40 100644 --- a/src/store/reducers/todo.js +++ b/src/store/reducers/todo.js @@ -35,8 +35,11 @@ const reducer = (state = initialState, action) => { }); return { ...state, todos: deletedTodos }; case actionTypes.GET_TODO: + /* const target = { ...state.todos[action.targetID - 1] }; - return { ...state, selectedTodo: target }; + return { ...state, selectedTodo: target };*/ + const selectedTodo = state.todos.find(td=> td.id===action.targetID); + return {...state, selectedTodo}; default: break; } From 6c05b2ea9d7117b8d149069d7e379609fa1cfa65 Mon Sep 17 00:00:00 2001 From: gina7484 <46814676+gina7484@users.noreply.github.com> Date: Fri, 25 Sep 2020 20:15:17 +0900 Subject: [PATCH 4/5] fourth commit --- src/containers/TodoList/TodoList.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/containers/TodoList/TodoList.js b/src/containers/TodoList/TodoList.js index 5319cfa..f1c638d 100644 --- a/src/containers/TodoList/TodoList.js +++ b/src/containers/TodoList/TodoList.js @@ -41,12 +41,14 @@ class TodoList extends Component { }); let todo = null; + /* if (this.state.selectedTodo) { todo = } + */ return (
From fa3765d0af92d9d9b8e9f0d0b9349b66a4a656d1 Mon Sep 17 00:00:00 2001 From: gina7484 <46814676+gina7484@users.noreply.github.com> Date: Fri, 25 Sep 2020 20:55:24 +0900 Subject: [PATCH 5/5] last --- package.json | 4 +- src/containers/TodoList/NewTodo/NewTodo.js | 7 +- .../TodoList/RealDetail/RealDetail.js | 5 +- src/containers/TodoList/TodoList.js | 19 ++--- src/index.js | 4 +- src/store/actions/index.js | 1 + src/store/actions/todo.js | 72 +++++++++++++++++++ src/store/reducers/todo.js | 18 +++-- yarn.lock | 5 ++ 9 files changed, 106 insertions(+), 29 deletions(-) create mode 100644 src/store/actions/index.js create mode 100644 src/store/actions/todo.js diff --git a/package.json b/package.json index 225cbeb..84d3985 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "swppfront", "version": "0.1.0", "private": true, + "proxy": "http://localhost:8000", "dependencies": { "react": "^16.9.0", "react-dom": "^16.9.0", @@ -9,7 +10,8 @@ "react-router": "^5.0.1", "react-router-dom": "^5.0.1", "react-scripts": "3.1.1", - "redux": "^4.0.5" + "redux": "^4.0.5", + "redux-thunk": "^2.3.0" }, "scripts": { "start": "react-scripts start", diff --git a/src/containers/TodoList/NewTodo/NewTodo.js b/src/containers/TodoList/NewTodo/NewTodo.js index 4ac88dc..01a1aa3 100644 --- a/src/containers/TodoList/NewTodo/NewTodo.js +++ b/src/containers/TodoList/NewTodo/NewTodo.js @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; import * as actionTypes from '../../../store/actions/actionTypes'; +import * as actionCreators from '../../../store/actions/index'; //all of them are inside actionTypes import './NewTodo.css'; @@ -15,7 +16,6 @@ class NewTodo extends Component { postTodoHandler = () => { this.props.onStoreTodo(this.state.title, this.state.content); - this.props.history.push('/todos'); } render() { @@ -42,10 +42,7 @@ class NewTodo extends Component { const mapDispatchToProps = dispatch => { return { onStoreTodo: (title, content) => - dispatch({ - type: actionTypes.ADD_TODO, - title: title, - content: content, }), + dispatch(actionCreators.postTodo({ title: title, content: content })), } }; diff --git a/src/containers/TodoList/RealDetail/RealDetail.js b/src/containers/TodoList/RealDetail/RealDetail.js index b3273fd..1d87118 100644 --- a/src/containers/TodoList/RealDetail/RealDetail.js +++ b/src/containers/TodoList/RealDetail/RealDetail.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; - +import * as actionCreators from '../../../store/actions/index'; import './RealDetail.css'; import { connect } from 'react-redux'; @@ -49,8 +49,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { onGetTodo: id => - dispatch({ type: actionTypes.GET_TODO, targetID: id }), + dispatch(actionCreators.getTodo(id)), } } - export default connect(mapStateToProps, mapDispatchToProps)(RealDetail); diff --git a/src/containers/TodoList/TodoList.js b/src/containers/TodoList/TodoList.js index f1c638d..6a52a36 100644 --- a/src/containers/TodoList/TodoList.js +++ b/src/containers/TodoList/TodoList.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; - +import axios from 'axios'; import Todo from '../../components/Todo/Todo'; import TodoDetail from '../../components/TodoDetail/TodoDetail'; @@ -11,14 +11,15 @@ import './TodoList.css'; import { connect } from 'react-redux'; import { withRouter } from 'react-router'; import * as actionTypes from '../../store/actions/actionTypes'; +import * as actionTypes from '../../store/actions/index'; class TodoList extends Component { + componentDidMount() { + this.props.onGetAll(); + } + state = { - todos: [ - { id: 1, title: 'SWPP', content: 'take swpp class', done: true }, - { id: 2, title: 'Movie', content: 'watch movie', done: false }, - { id: 3, title: 'Dinner', content: 'eat dinner', done: false } - ], + todos: [], selectedTodo: null, } @@ -73,9 +74,11 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { onToggleTodo: (id) => - dispatch({ type: actionTypes.TOGGLE_DONE, targetID: id }), + dispatch(actionCreators.toggleTodo(id)), onDeleteTodo: (id) => - dispatch({ type: actionTypes.DELETE_TODO, targetID: id }), + dispatch(actionCreators.deleteTodo(id)), + onGetAll: () => + dispatch(actionCreators.getTodos()) } } diff --git a/src/index.js b/src/index.js index 00dd1c5..96dcbcb 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,7 @@ import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; import { Provider } from 'react-redux'; - +import thunk from 'redux-thunk'; import { createStore, combineReducers, applyMiddleware, compose } from 'redux'; //import thunk from 'redux-thunk'; //import { connectRouter, routerMiddleware } from 'connected-react-router'; @@ -16,7 +16,7 @@ const rootReducer = combineReducers({ }); -const store = createStore(rootReducer); +const store = createStore(rootReducer,applyMiddleware(thunk)); diff --git a/src/store/actions/index.js b/src/store/actions/index.js new file mode 100644 index 0000000..f0d56e1 --- /dev/null +++ b/src/store/actions/index.js @@ -0,0 +1 @@ +export {getTodos, postTodo, deleteTodo, toggleTodo,getTodo} from './todo'; \ No newline at end of file diff --git a/src/store/actions/todo.js b/src/store/actions/todo.js new file mode 100644 index 0000000..4e02f88 --- /dev/null +++ b/src/store/actions/todo.js @@ -0,0 +1,72 @@ +import * as actionTypes from './actionTypes'; +import axios from 'axios'; + +export const getTodos_ = (todos) => { + return { type: actionTypes.GET_ALL, todos: todos }; + }; + +export const getTodos = () => { + return dispatch => { + return axios.get('/api/todo/') + .then(res => dispatch(getTodos_(res.data))); + }; +}; + +export const getTodo_ = (todo) => { + return { type: actionTypes.GET_TODO, target: todo }; + }; + + export const getTodo = (id) => { + return dispatch => { + return axios.get('/api/todo/' + id) + .then(res => { + dispatch(getTodo_(res.data)) + }); + }; + }; + +export const postTodo_ = (td) => { + return { + type: actionTypes.ADD_TODO, + id: td.id, + title: td.title, + content: td.content, + }; + }; + +export const postTodo = (td) => { + return (dispatch) => { + return axios.post('/api/todo/', td) + .then(res => { + dispatch(postTodo_(res.data)); + }); + }; + }; + + export const deleteTodo_ = (id) => { + return { + type: actionTypes.DELETE_TODO, + targetID: id + }; + }; + + export const deleteTodo = (id) => { + return dispatch => { + return axios.delete('/api/todo/' + id) + .then(res => dispatch(deleteTodo_(id))); + }; + }; + + export const toggleTodo_ = (id) => { + return { + type: actionTypes.TOGGLE_DONE, + targetID: id + }; + }; + + export const toggleTodo = (id) => { + return dispatch => { + return axios.put('/api/todo/' + id) + .then(res => dispatch(toggleTodo_(id))); + }; + }; \ No newline at end of file diff --git a/src/store/reducers/todo.js b/src/store/reducers/todo.js index 791ea40..8384001 100644 --- a/src/store/reducers/todo.js +++ b/src/store/reducers/todo.js @@ -13,12 +13,12 @@ const reducer = (state = initialState, action) => { switch (action.type) { case actionTypes.ADD_TODO: const newTodo = { - id: state.todos.length + 1, - title: action.title, content: action.content, - done: false + id: action.id, + title: action.title, + content: action.content, + done: action.done, }; - // state.todos.push(newTodo);//Bad!! - return { ...state, todos: [...state.todos,newTodo] }; + return { ...state, todos: state.todos.concat(newTodo) }; // concat has the same meaning case actionTypes.TOGGLE_DONE: const modified = state.todos.map((td) => { @@ -35,11 +35,9 @@ const reducer = (state = initialState, action) => { }); return { ...state, todos: deletedTodos }; case actionTypes.GET_TODO: - /* - const target = { ...state.todos[action.targetID - 1] }; - return { ...state, selectedTodo: target };*/ - const selectedTodo = state.todos.find(td=> td.id===action.targetID); - return {...state, selectedTodo}; + return { ...state, selectedTodo: action.target }; + case actionTypes.GET_ALL: + return { ...state, todos: action.todos }; default: break; } diff --git a/yarn.lock b/yarn.lock index 08f6b55..685e32e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8152,6 +8152,11 @@ recursive-readdir@2.2.2: dependencies: minimatch "3.0.4" +redux-thunk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" + integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== + redux@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"