Skip to content

Instantly share code, notes, and snippets.

@yashikagarg13
Created March 20, 2017 03:44
Show Gist options
  • Save yashikagarg13/80b9d6bed062e90e0fc2cb4dd3b918fc to your computer and use it in GitHub Desktop.
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
<!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: &nbsp;&nbsp;
<FilterLink filter="SHOW_ALL">
All</FilterLink>&nbsp;&nbsp;
<FilterLink filter="SHOW_ACTIVE">
Active</FilterLink>&nbsp;&nbsp;
<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>
"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