Created
March 20, 2017 03:44
-
-
Save yashikagarg13/80b9d6bed062e90e0fc2cb4dd3b918fc to your computer and use it in GitHub Desktop.
Todo App - React + Redux - Refactored into Presentational and Container components // source https://jsbin.com/keqexaj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>JS Bin</title> | |
<script src="https://unpkg.com/react@15/dist/react.js"></script> | |
<script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script> | |
<script src="https://wzrd.in/standalone/deep-freeze@latest"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.js"></script> | |
</head> | |
<body> | |
<div id="app"></div> | |
<script id="jsbin-javascript"> | |
"use strict"; | |
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | |
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | |
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | |
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
var todoReducer = function todoReducer(state, action) { | |
if (state === undefined) state = {}; | |
switch (action.type) { | |
case "ADD_TODO": | |
return _extends({}, action.todo, { completed: false }); | |
case "TOGGLE_TODO": | |
if (state.id !== action.id) { | |
return state; | |
} | |
return _extends({}, state, { | |
completed: !state.completed | |
}); | |
default: | |
return state; | |
} | |
}; | |
var todosReducer = function todosReducer(state, action) { | |
if (state === undefined) state = []; | |
switch (action.type) { | |
case "ADD_TODO": | |
return [].concat(_toConsumableArray(state), [todoReducer(undefined, action)]); | |
case "TOGGLE_TODO": | |
return state.map(function (todo) { | |
return todoReducer(todo, action); | |
}); | |
default: | |
return state; | |
} | |
}; | |
var visbilityFilterReducer = function visbilityFilterReducer(state, action) { | |
if (state === undefined) state = "SHOW_ALL"; | |
switch (action.type) { | |
case "SET_VISIBILITY_FILTER": | |
return action.filter; | |
default: | |
return state; | |
} | |
}; | |
var _Redux = Redux; | |
var combineReducers = _Redux.combineReducers; | |
var todoAppReducer = combineReducers({ | |
todos: todosReducer, | |
visbilityFilter: visbilityFilterReducer | |
}); | |
var _Redux2 = Redux; | |
var createStore = _Redux2.createStore; | |
var store = createStore(todoAppReducer); | |
var _React = React; | |
var Component = _React.Component; | |
var getVisibleTodos = function getVisibleTodos(todos, filter) { | |
switch (filter) { | |
case "SHOW_ALL": | |
return todos; | |
case "SHOW_ACTIVE": | |
return todos.filter(function (t) { | |
return !t.completed; | |
}); | |
case "SHOW_COMPLETED": | |
return todos.filter(function (t) { | |
return t.completed; | |
}); | |
default: | |
return todos; | |
} | |
}; | |
var nextTodoId = 0; | |
var Link = function Link(_ref) { | |
var active = _ref.active; | |
var onClick = _ref.onClick; | |
var children = _ref.children; | |
return active ? React.createElement( | |
"span", | |
null, | |
children | |
) : React.createElement( | |
"a", | |
{ href: "#", | |
onClick: function (e) { | |
e.preventDefault(); | |
onClick(); | |
} }, | |
children | |
); | |
}; | |
var FilterLink = (function (_Component) { | |
_inherits(FilterLink, _Component); | |
function FilterLink() { | |
_classCallCheck(this, FilterLink); | |
_get(Object.getPrototypeOf(FilterLink.prototype), "constructor", this).apply(this, arguments); | |
} | |
_createClass(FilterLink, [{ | |
key: "componentDidMount", | |
value: function componentDidMount() { | |
var _this = this; | |
this.unsubscribe = store.subscribe(function () { | |
_this.forceUpdate(); | |
}); | |
} | |
}, { | |
key: "componentWillUnmount", | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: "render", | |
value: function render() { | |
var _this2 = this; | |
var currentFilter = store.getState().visbilityFilter; | |
return React.createElement( | |
Link, | |
{ | |
active: this.props.filter === currentFilter, | |
onClick: function () { | |
store.dispatch({ | |
type: "SET_VISIBILITY_FILTER", | |
filter: _this2.props.filter | |
}); | |
} | |
}, | |
this.props.children | |
); | |
} | |
}]); | |
return FilterLink; | |
})(Component); | |
var ToDo = function ToDo(_ref2) { | |
var id = _ref2.id; | |
var text = _ref2.text; | |
var completed = _ref2.completed; | |
var toggleTodo = _ref2.toggleTodo; | |
var completedStyle = { | |
textDecoration: "line-through" | |
}; | |
return React.createElement( | |
"li", | |
{ onClick: toggleTodo.bind(null, id), | |
style: completed ? completedStyle : null }, | |
text | |
); | |
}; | |
var ToDoList = function ToDoList(_ref3) { | |
var todos = _ref3.todos; | |
var toggleTodo = _ref3.toggleTodo; | |
return React.createElement( | |
"ul", | |
null, | |
todos.map(function (todo) { | |
return React.createElement(ToDo, _extends({ | |
key: todo.id | |
}, todo, { | |
toggleTodo: toggleTodo })); | |
}) | |
); | |
}; | |
// This component is neither presentational nor container. | |
// This is kept along with behaviour because we can not break down further. | |
var AddTodo = function AddTodo() { | |
var input = undefined; | |
return React.createElement( | |
"div", | |
null, | |
React.createElement("input", { type: "text", ref: function (node) { | |
input = node; | |
} }), | |
React.createElement( | |
"button", | |
{ type: "button", | |
onClick: function () { | |
store.dispatch({ | |
type: "ADD_TODO", | |
todo: { | |
text: input.value, | |
id: ++nextTodoId | |
} | |
}); | |
input.value = ""; | |
} }, | |
"Submit" | |
) | |
); | |
}; | |
var Footer = function Footer() { | |
return React.createElement( | |
"p", | |
null, | |
"Show: ", | |
React.createElement( | |
FilterLink, | |
{ filter: "SHOW_ALL" }, | |
"All" | |
), | |
" ", | |
React.createElement( | |
FilterLink, | |
{ filter: "SHOW_ACTIVE" }, | |
"Active" | |
), | |
" ", | |
React.createElement( | |
FilterLink, | |
{ filter: "SHOW_COMPLETED" }, | |
"Completed" | |
) | |
); | |
}; | |
var VisibleTodoList = (function (_Component2) { | |
_inherits(VisibleTodoList, _Component2); | |
function VisibleTodoList() { | |
_classCallCheck(this, VisibleTodoList); | |
_get(Object.getPrototypeOf(VisibleTodoList.prototype), "constructor", this).apply(this, arguments); | |
} | |
_createClass(VisibleTodoList, [{ | |
key: "componentDidMount", | |
value: function componentDidMount() { | |
var _this3 = this; | |
this.unsubscribe = store.subscribe(function () { | |
_this3.forceUpdate(); | |
}); | |
} | |
}, { | |
key: "componentWillUnmount", | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: "render", | |
value: function render() { | |
var props = this.props; | |
var state = store.getState(); | |
return React.createElement(ToDoList, { | |
todos: getVisibleTodos(state.todos, state.visbilityFilter), | |
toggleTodo: function (id) { | |
store.dispatch({ | |
type: "TOGGLE_TODO", | |
id: id | |
}); | |
} | |
}); | |
} | |
}]); | |
return VisibleTodoList; | |
})(Component); | |
var TodoApp = function TodoApp() { | |
return React.createElement( | |
"div", | |
null, | |
React.createElement(AddTodo, null), | |
React.createElement(VisibleTodoList, null), | |
React.createElement(Footer, null) | |
); | |
}; | |
ReactDOM.render(React.createElement(TodoApp, null), document.getElementById("app")); | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">const todoReducer = (state = {}, action) => { | |
switch(action.type) { | |
case "ADD_TODO": | |
return {...action.todo, completed: false}; | |
case "TOGGLE_TODO": | |
if (state.id !== action.id) { | |
return state; | |
} | |
return { | |
...state, | |
completed: !state.completed | |
} | |
default: | |
return state; | |
} | |
} | |
const todosReducer = (state = [], action) => { | |
switch(action.type) { | |
case "ADD_TODO": | |
return [...state, todoReducer(undefined, action)]; | |
case "TOGGLE_TODO": | |
return state.map(todo => todoReducer(todo, action)); | |
default: | |
return state; | |
} | |
} | |
const visbilityFilterReducer = (state = "SHOW_ALL", action) => { | |
switch(action.type) { | |
case "SET_VISIBILITY_FILTER": | |
return action.filter; | |
default: | |
return state; | |
} | |
} | |
const {combineReducers} = Redux; | |
const todoAppReducer = combineReducers({ | |
todos: todosReducer, | |
visbilityFilter: visbilityFilterReducer, | |
}); | |
const {createStore} = Redux; | |
const store = createStore(todoAppReducer); | |
const {Component} = React | |
const getVisibleTodos = (todos, filter) => { | |
switch(filter) { | |
case "SHOW_ALL": | |
return todos; | |
case "SHOW_ACTIVE": | |
return todos.filter(t => !t.completed); | |
case "SHOW_COMPLETED": | |
return todos.filter(t => t.completed); | |
default: | |
return todos; | |
} | |
} | |
let nextTodoId = 0; | |
const Link = ({ | |
active, | |
onClick, | |
children | |
}) => { | |
return active | |
? <span>{children}</span> | |
: <a href= "#" | |
onClick={e => { | |
e.preventDefault(); | |
onClick(); | |
} | |
}> | |
{children} | |
</a> | |
}; | |
class FilterLink extends Component { | |
componentDidMount() { | |
this.unsubscribe = store.subscribe(() => { | |
this.forceUpdate(); | |
}); | |
} | |
componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
render () { | |
let currentFilter = store.getState().visbilityFilter; | |
return ( | |
<Link | |
active={this.props.filter === currentFilter} | |
onClick={() => { | |
store.dispatch({ | |
type: "SET_VISIBILITY_FILTER", | |
filter: this.props.filter | |
}) | |
}} | |
>{this.props.children}</Link> | |
); | |
} | |
} | |
const ToDo = ({id, text, completed, toggleTodo}) => { | |
const completedStyle = { | |
textDecoration: "line-through", | |
}; | |
return ( | |
<li onClick={toggleTodo.bind(null, id)} | |
style={completed ? completedStyle : null }> | |
{text}</li> | |
); | |
} | |
const ToDoList = ({todos, toggleTodo}) => { | |
return ( | |
<ul> | |
{todos.map(todo => | |
<ToDo | |
key={todo.id} | |
{...todo} | |
toggleTodo={toggleTodo} /> | |
)} | |
</ul> | |
); | |
} | |
// This component is neither presentational nor container. | |
// This is kept along with behaviour because we can not break down further. | |
const AddTodo = () => { | |
let input; | |
return ( | |
<div> | |
<input type="text" ref={node => {input = node;}} /> | |
<button type="button" | |
onClick={() => { | |
store.dispatch({ | |
type: "ADD_TODO", | |
todo: { | |
text: input.value, | |
id: ++nextTodoId | |
} | |
}); | |
input.value = ""; | |
}}>Submit</button> | |
</div> | |
); | |
} | |
const Footer = () => { | |
return ( | |
<p>Show: | |
<FilterLink filter="SHOW_ALL"> | |
All</FilterLink> | |
<FilterLink filter="SHOW_ACTIVE"> | |
Active</FilterLink> | |
<FilterLink filter="SHOW_COMPLETED"> | |
Completed</FilterLink> | |
</p> | |
); | |
} | |
class VisibleTodoList extends Component { | |
componentDidMount() { | |
this.unsubscribe = store.subscribe(() => { | |
this.forceUpdate(); | |
}); | |
} | |
componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
render () { | |
const props = this.props; | |
const state = store.getState(); | |
return ( | |
<ToDoList | |
todos={getVisibleTodos(state.todos, state.visbilityFilter)} | |
toggleTodo={id => { | |
store.dispatch({ | |
type: "TOGGLE_TODO", | |
id, | |
}); | |
}} | |
/> | |
); | |
} | |
} | |
const TodoApp = () => { | |
return ( | |
<div> | |
<AddTodo/> | |
<VisibleTodoList /> | |
<Footer /> | |
</div> | |
); | |
} | |
ReactDOM.render(<TodoApp />, document.getElementById("app")); | |
</script></body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | |
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | |
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | |
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
var todoReducer = function todoReducer(state, action) { | |
if (state === undefined) state = {}; | |
switch (action.type) { | |
case "ADD_TODO": | |
return _extends({}, action.todo, { completed: false }); | |
case "TOGGLE_TODO": | |
if (state.id !== action.id) { | |
return state; | |
} | |
return _extends({}, state, { | |
completed: !state.completed | |
}); | |
default: | |
return state; | |
} | |
}; | |
var todosReducer = function todosReducer(state, action) { | |
if (state === undefined) state = []; | |
switch (action.type) { | |
case "ADD_TODO": | |
return [].concat(_toConsumableArray(state), [todoReducer(undefined, action)]); | |
case "TOGGLE_TODO": | |
return state.map(function (todo) { | |
return todoReducer(todo, action); | |
}); | |
default: | |
return state; | |
} | |
}; | |
var visbilityFilterReducer = function visbilityFilterReducer(state, action) { | |
if (state === undefined) state = "SHOW_ALL"; | |
switch (action.type) { | |
case "SET_VISIBILITY_FILTER": | |
return action.filter; | |
default: | |
return state; | |
} | |
}; | |
var _Redux = Redux; | |
var combineReducers = _Redux.combineReducers; | |
var todoAppReducer = combineReducers({ | |
todos: todosReducer, | |
visbilityFilter: visbilityFilterReducer | |
}); | |
var _Redux2 = Redux; | |
var createStore = _Redux2.createStore; | |
var store = createStore(todoAppReducer); | |
var _React = React; | |
var Component = _React.Component; | |
var getVisibleTodos = function getVisibleTodos(todos, filter) { | |
switch (filter) { | |
case "SHOW_ALL": | |
return todos; | |
case "SHOW_ACTIVE": | |
return todos.filter(function (t) { | |
return !t.completed; | |
}); | |
case "SHOW_COMPLETED": | |
return todos.filter(function (t) { | |
return t.completed; | |
}); | |
default: | |
return todos; | |
} | |
}; | |
var nextTodoId = 0; | |
var Link = function Link(_ref) { | |
var active = _ref.active; | |
var onClick = _ref.onClick; | |
var children = _ref.children; | |
return active ? React.createElement( | |
"span", | |
null, | |
children | |
) : React.createElement( | |
"a", | |
{ href: "#", | |
onClick: function (e) { | |
e.preventDefault(); | |
onClick(); | |
} }, | |
children | |
); | |
}; | |
var FilterLink = (function (_Component) { | |
_inherits(FilterLink, _Component); | |
function FilterLink() { | |
_classCallCheck(this, FilterLink); | |
_get(Object.getPrototypeOf(FilterLink.prototype), "constructor", this).apply(this, arguments); | |
} | |
_createClass(FilterLink, [{ | |
key: "componentDidMount", | |
value: function componentDidMount() { | |
var _this = this; | |
this.unsubscribe = store.subscribe(function () { | |
_this.forceUpdate(); | |
}); | |
} | |
}, { | |
key: "componentWillUnmount", | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: "render", | |
value: function render() { | |
var _this2 = this; | |
var currentFilter = store.getState().visbilityFilter; | |
return React.createElement( | |
Link, | |
{ | |
active: this.props.filter === currentFilter, | |
onClick: function () { | |
store.dispatch({ | |
type: "SET_VISIBILITY_FILTER", | |
filter: _this2.props.filter | |
}); | |
} | |
}, | |
this.props.children | |
); | |
} | |
}]); | |
return FilterLink; | |
})(Component); | |
var ToDo = function ToDo(_ref2) { | |
var id = _ref2.id; | |
var text = _ref2.text; | |
var completed = _ref2.completed; | |
var toggleTodo = _ref2.toggleTodo; | |
var completedStyle = { | |
textDecoration: "line-through" | |
}; | |
return React.createElement( | |
"li", | |
{ onClick: toggleTodo.bind(null, id), | |
style: completed ? completedStyle : null }, | |
text | |
); | |
}; | |
var ToDoList = function ToDoList(_ref3) { | |
var todos = _ref3.todos; | |
var toggleTodo = _ref3.toggleTodo; | |
return React.createElement( | |
"ul", | |
null, | |
todos.map(function (todo) { | |
return React.createElement(ToDo, _extends({ | |
key: todo.id | |
}, todo, { | |
toggleTodo: toggleTodo })); | |
}) | |
); | |
}; | |
// This component is neither presentational nor container. | |
// This is kept along with behaviour because we can not break down further. | |
var AddTodo = function AddTodo() { | |
var input = undefined; | |
return React.createElement( | |
"div", | |
null, | |
React.createElement("input", { type: "text", ref: function (node) { | |
input = node; | |
} }), | |
React.createElement( | |
"button", | |
{ type: "button", | |
onClick: function () { | |
store.dispatch({ | |
type: "ADD_TODO", | |
todo: { | |
text: input.value, | |
id: ++nextTodoId | |
} | |
}); | |
input.value = ""; | |
} }, | |
"Submit" | |
) | |
); | |
}; | |
var Footer = function Footer() { | |
return React.createElement( | |
"p", | |
null, | |
"Show: ", | |
React.createElement( | |
FilterLink, | |
{ filter: "SHOW_ALL" }, | |
"All" | |
), | |
" ", | |
React.createElement( | |
FilterLink, | |
{ filter: "SHOW_ACTIVE" }, | |
"Active" | |
), | |
" ", | |
React.createElement( | |
FilterLink, | |
{ filter: "SHOW_COMPLETED" }, | |
"Completed" | |
) | |
); | |
}; | |
var VisibleTodoList = (function (_Component2) { | |
_inherits(VisibleTodoList, _Component2); | |
function VisibleTodoList() { | |
_classCallCheck(this, VisibleTodoList); | |
_get(Object.getPrototypeOf(VisibleTodoList.prototype), "constructor", this).apply(this, arguments); | |
} | |
_createClass(VisibleTodoList, [{ | |
key: "componentDidMount", | |
value: function componentDidMount() { | |
var _this3 = this; | |
this.unsubscribe = store.subscribe(function () { | |
_this3.forceUpdate(); | |
}); | |
} | |
}, { | |
key: "componentWillUnmount", | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: "render", | |
value: function render() { | |
var props = this.props; | |
var state = store.getState(); | |
return React.createElement(ToDoList, { | |
todos: getVisibleTodos(state.todos, state.visbilityFilter), | |
toggleTodo: function (id) { | |
store.dispatch({ | |
type: "TOGGLE_TODO", | |
id: id | |
}); | |
} | |
}); | |
} | |
}]); | |
return VisibleTodoList; | |
})(Component); | |
var TodoApp = function TodoApp() { | |
return React.createElement( | |
"div", | |
null, | |
React.createElement(AddTodo, null), | |
React.createElement(VisibleTodoList, null), | |
React.createElement(Footer, null) | |
); | |
}; | |
ReactDOM.render(React.createElement(TodoApp, null), document.getElementById("app")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment