Created
December 3, 2019 22:49
-
-
Save raydot/fd28a2eef06c768c4ca2c540eff11f65 to your computer and use it in GitHub Desktop.
Redux Tutorial Video 24 -- Passing the Store Down Explicitly via Props // source https://jsbin.com/neseqom
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 name="description" content="Video 24 -- Passing the Store Down Explicitly via Props"> | |
<meta charset="utf-8"> | |
<title>Redux Tutorial</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.4/redux.min.js"></script> | |
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> | |
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> | |
</head> | |
<body> | |
<div id='root'></div> | |
<script id="jsbin-javascript"> | |
// This wouldn't work in real life because: | |
// 1. Container components hard to test because they reference same store. | |
// 2. Hard to create universal applications becuase you want to render different stores for different request. | |
// So let's set it up where all containers read the store from the props, as fed to it by the render calls. | |
// Note this does not change the data flow, they're just not accessing a top level variable. | |
'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 todo = function todo(state, action) { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
if (state.id !== action.id) { | |
return state; | |
} | |
return _extends({}, state, { | |
completed: !state.completed | |
}); | |
default: | |
return state; | |
} | |
}; | |
// todos reducer | |
var todos = function todos(state, action) { | |
if (state === undefined) state = []; | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [].concat(_toConsumableArray(state), [// return array with all items + new | |
todo(undefined, action) // calls child reducers | |
]); | |
case 'TOGGLE_TODO': | |
return state.map(function (t) { | |
return todo(t, action); | |
}); | |
default: | |
return state; | |
} | |
}; | |
var visibilityFilter = function visibilityFilter(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; | |
// This is the root reducer | |
var todoApp = combineReducers({ | |
todos: todos, | |
visibilityFilter: visibilityFilter | |
}); | |
var _React = React; | |
var Component = _React.Component; | |
// react presentational component for utilizing visibility filter | |
var Link = function Link(_ref) { | |
var active = _ref.active; | |
var children = _ref.children; | |
var onClick = _ref.onClick; | |
if (active) { | |
return React.createElement( | |
'span', | |
null, | |
children | |
); | |
} | |
return React.createElement( | |
'a', | |
{ href: '#', | |
onClick: function (e) { | |
e.preventDefault(); | |
onClick(); | |
} | |
}, | |
children | |
); | |
}; | |
// container to provide data and behavior to presentational component | |
// Renders linked based on props and Redux store state | |
var FilterLink = (function (_Component) { | |
_inherits(FilterLink, _Component); | |
function FilterLink() { | |
_classCallCheck(this, FilterLink); | |
_get(Object.getPrototypeOf(FilterLink.prototype), 'constructor', this).apply(this, arguments); | |
} | |
// Presentational component | |
_createClass(FilterLink, [{ | |
key: 'componentDidMount', | |
value: function componentDidMount() { | |
var _this = this; | |
var store = this.props.store; | |
this.unsubscribe = store.subscribe(function () { | |
return _this.forceUpdate(); | |
}); | |
} | |
}, { | |
key: 'componentWillUnmount', | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: 'render', | |
value: function render() { | |
var props = this.props; | |
var store = props.store; | |
var state = store.getState(); | |
// delegate rendering to presentational component. | |
return React.createElement( | |
Link, | |
{ | |
active: props.filter === state.visibilityFilter, | |
onClick: function () { | |
return store.dispatch({ | |
type: 'SET_VISIBILITY_FILTER', | |
filter: props.filter | |
}); | |
} | |
}, | |
props.children | |
); //return | |
} | |
}]); | |
return FilterLink; | |
})(Component); | |
var Footer = function Footer(_ref2) { | |
var store = _ref2.store; | |
return React.createElement( | |
'p', | |
null, | |
'Show:', | |
' ', | |
React.createElement( | |
FilterLink, | |
{ | |
filter: 'SHOW_ALL', | |
store: store | |
}, | |
'All' | |
), | |
', ', | |
React.createElement( | |
FilterLink, | |
{ | |
filter: 'SHOW_ACTIVE', | |
store: store | |
}, | |
'Active' | |
), | |
', ', | |
React.createElement( | |
FilterLink, | |
{ | |
filter: 'SHOW_COMPLETED', | |
store: store | |
}, | |
'Completed' | |
) | |
); | |
}; | |
// Purely presentational Todo component | |
var Todo = function Todo(_ref3) { | |
var onClick = _ref3.onClick; | |
var completed = _ref3.completed; | |
var text = _ref3.text; | |
var id = _ref3.id; | |
return React.createElement( | |
'li', | |
{ | |
onClick: onClick, | |
style: { | |
textDecoration: completed ? 'line-through' : 'none' | |
} | |
}, | |
id, | |
': ', | |
text | |
); | |
}; | |
// Purely presentational TodoList | |
var TodoList = function TodoList(_ref4) { | |
var todos = _ref4.todos; | |
var onTodoClick = _ref4.onTodoClick; | |
return React.createElement( | |
'ul', | |
null, | |
todos.map(function (todo) { | |
return React.createElement(Todo, _extends({ | |
key: todo.id | |
}, todo, { | |
onClick: function () { | |
return onTodoClick(todo.id); | |
} | |
})); | |
}) | |
); | |
}; | |
// Not really presentational or container | |
var nextTodoId = 0; | |
var AddTodo = function AddTodo(_ref5) { | |
var store = _ref5.store; | |
var input = undefined; | |
return React.createElement( | |
'div', | |
null, | |
React.createElement('input', { ref: function (node) { | |
input = node; | |
} }), | |
React.createElement( | |
'button', | |
{ onClick: function () { | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id: nextTodoId++, | |
text: input.value | |
}); | |
input.value = ''; | |
} }, | |
'Add Todo' | |
) | |
); | |
}; | |
var getVisibleTodos = function getVisibleTodos(todos, filter) { | |
switch (filter) { | |
case 'SHOW_ALL': | |
return todos; | |
case 'SHOW_COMPLETED': | |
return todos.filter(function (t) { | |
return t.completed; | |
}); | |
case 'SHOW_ACTIVE': | |
return todos.filter(function (t) { | |
return !t.completed; | |
}); | |
} | |
}; | |
// Container component. | |
// subscribes to store and rerenders todo list when store state changes | |
// calculates visible todos based on redux store state | |
// Rendering is performed by TodoList component. | |
var VisibleTodoList = (function (_Component2) { | |
_inherits(VisibleTodoList, _Component2); | |
function VisibleTodoList() { | |
_classCallCheck(this, VisibleTodoList); | |
_get(Object.getPrototypeOf(VisibleTodoList.prototype), 'constructor', this).apply(this, arguments); | |
} | |
// With the refactor of TodoList, AddTodo, and Footer, TodoApp() this is now acting as a container component. | |
_createClass(VisibleTodoList, [{ | |
key: 'componentDidMount', | |
value: function componentDidMount() { | |
var _this2 = this; | |
var store = this.props.store; | |
this.unsubscribe = store.subscribe(function () { | |
return _this2.forceUpdate(); | |
}); | |
} | |
}, { | |
key: 'componentWillUnmount', | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: 'render', | |
value: function render() { | |
var props = this.props; | |
var store = props.store; | |
var state = store.getState(); | |
return React.createElement(TodoList, { | |
todos: getVisibleTodos(state.todos, state.visibilityFilter), | |
onTodoClick: function (id) { | |
return store.dispatch({ | |
type: 'TOGGLE_TODO', | |
id: id | |
}); | |
} | |
}); | |
} | |
}]); | |
return VisibleTodoList; | |
})(Component); | |
var TodoApp = function TodoApp(_ref6) { | |
var store = _ref6.store; | |
return React.createElement( | |
'div', | |
null, | |
React.createElement(AddTodo, { store: store }), | |
React.createElement(VisibleTodoList, { store: store }), | |
React.createElement(Footer, { store: store }) | |
); | |
}; | |
// Create store | |
var _Redux2 = Redux; | |
var createStore = _Redux2.createStore; | |
ReactDOM.render(React.createElement(TodoApp, { store: createStore(todoApp) }), document.getElementById('root')); | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">// This wouldn't work in real life because: | |
// 1. Container components hard to test because they reference same store. | |
// 2. Hard to create universal applications becuase you want to render different stores for different request. | |
// So let's set it up where all containers read the store from the props, as fed to it by the render calls. | |
// Note this does not change the data flow, they're just not accessing a top level variable. | |
const todo = ( state, action ) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
if (state.id !== action.id) { | |
return state; | |
} | |
return { | |
...state, | |
completed: !state.completed | |
} | |
default: | |
return state | |
} | |
} | |
// todos reducer | |
const todos = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [ | |
...state, // return array with all items + new | |
todo(undefined, action) // calls child reducers | |
] | |
case 'TOGGLE_TODO': | |
return state.map(t => todo(t, action)) | |
default: | |
return state; | |
} | |
}; | |
const visibilityFilter = ( | |
state = 'SHOW_ALL', | |
action | |
) => { | |
switch (action.type) { | |
case 'SET_VISIBILITY_FILTER': | |
return action.filter; | |
default: | |
return state; | |
} | |
} | |
const { combineReducers } = Redux | |
// This is the root reducer | |
const todoApp = combineReducers({ | |
todos, | |
visibilityFilter | |
}) | |
const { Component } = React | |
// react presentational component for utilizing visibility filter | |
const Link = ({ | |
active, | |
children, | |
onClick | |
}) => { | |
if (active) { | |
return <span>{children}</span>; | |
} | |
return ( | |
<a href='#' | |
onClick={e => { | |
e.preventDefault(); | |
onClick() | |
}} | |
> | |
{children} | |
</a> | |
); | |
}; | |
// container to provide data and behavior to presentational component | |
// Renders linked based on props and Redux store state | |
class FilterLink extends Component { | |
componentDidMount() { | |
const { store } = this.props; | |
this.unsubscribe = store.subscribe(() => | |
this.forceUpdate() | |
); | |
} | |
componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
render() { | |
const props = this.props; | |
const { store } = props; | |
const state = store.getState(); | |
// delegate rendering to presentational component. | |
return ( | |
<Link | |
active={ | |
props.filter === | |
state.visibilityFilter | |
} | |
onClick = {() => | |
store.dispatch({ | |
type: 'SET_VISIBILITY_FILTER', | |
filter: props.filter | |
}) | |
} | |
> | |
{props.children} | |
</Link> | |
); //return | |
} | |
} | |
// Presentational component | |
const Footer = ({ store }) => ( | |
<p> | |
Show: | |
{' '} | |
<FilterLink | |
filter='SHOW_ALL' | |
store={store} | |
> | |
All | |
</FilterLink> | |
{', '} | |
<FilterLink | |
filter='SHOW_ACTIVE' | |
store={store} | |
> | |
Active | |
</FilterLink> | |
{', '} | |
<FilterLink | |
filter='SHOW_COMPLETED' | |
store={store} | |
> | |
Completed | |
</FilterLink> | |
</p> | |
); | |
// Purely presentational Todo component | |
const Todo = ({ | |
onClick, | |
completed, | |
text, | |
id | |
}) => ( | |
<li | |
onClick={onClick} | |
style={{ | |
textDecoration: | |
completed ? | |
'line-through' : | |
'none' | |
}} | |
> | |
{id}: {text} | |
</li> | |
); | |
// Purely presentational TodoList | |
const TodoList = ({ | |
todos, | |
onTodoClick | |
}) => ( | |
<ul> | |
{todos.map(todo => | |
<Todo | |
key={todo.id} | |
{...todo} | |
onClick={() => onTodoClick(todo.id)} | |
/> | |
)} | |
</ul> | |
); | |
// Not really presentational or container | |
let nextTodoId = 0; | |
const AddTodo = ({ store }) => { | |
let input; | |
return ( | |
<div> | |
<input ref={node => { | |
input = node; | |
}} /> | |
<button onClick = {() => { | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id: nextTodoId++, | |
text: input.value | |
}) | |
input.value = '' | |
}}> | |
Add Todo | |
</button> | |
</div> | |
); | |
}; | |
const getVisibleTodos = ( | |
todos, | |
filter | |
) => { | |
switch (filter) { | |
case 'SHOW_ALL': | |
return todos; | |
case 'SHOW_COMPLETED': | |
return todos.filter( | |
t => t.completed | |
); | |
case 'SHOW_ACTIVE': | |
return todos.filter( | |
t => !t.completed | |
); | |
} | |
} | |
// Container component. | |
// subscribes to store and rerenders todo list when store state changes | |
// calculates visible todos based on redux store state | |
// Rendering is performed by TodoList component. | |
class VisibleTodoList extends Component { | |
componentDidMount() { | |
const { store } = this.props | |
this.unsubscribe = store.subscribe(() => | |
this.forceUpdate() | |
); | |
} | |
componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
render() { | |
const props = this.props; | |
const { store } = props; | |
const state = store.getState() | |
return ( | |
<TodoList | |
todos={ | |
getVisibleTodos( | |
state.todos, | |
state.visibilityFilter | |
) | |
} | |
onTodoClick={id => | |
store.dispatch({ | |
type: 'TOGGLE_TODO', | |
id | |
}) | |
} | |
/> | |
); | |
} | |
} | |
// With the refactor of TodoList, AddTodo, and Footer, TodoApp() this is now acting as a container component. | |
const TodoApp = ({ store }) => ( | |
<div> | |
<AddTodo store={store} /> | |
<VisibleTodoList store={store} /> | |
<Footer store={store} /> | |
</div> | |
); | |
// Create store | |
const { createStore } = Redux | |
ReactDOM.render( | |
<TodoApp store={createStore(todoApp)} />, | |
document.getElementById('root') | |
) | |
</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
// This wouldn't work in real life because: | |
// 1. Container components hard to test because they reference same store. | |
// 2. Hard to create universal applications becuase you want to render different stores for different request. | |
// So let's set it up where all containers read the store from the props, as fed to it by the render calls. | |
// Note this does not change the data flow, they're just not accessing a top level variable. | |
'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 todo = function todo(state, action) { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
if (state.id !== action.id) { | |
return state; | |
} | |
return _extends({}, state, { | |
completed: !state.completed | |
}); | |
default: | |
return state; | |
} | |
}; | |
// todos reducer | |
var todos = function todos(state, action) { | |
if (state === undefined) state = []; | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [].concat(_toConsumableArray(state), [// return array with all items + new | |
todo(undefined, action) // calls child reducers | |
]); | |
case 'TOGGLE_TODO': | |
return state.map(function (t) { | |
return todo(t, action); | |
}); | |
default: | |
return state; | |
} | |
}; | |
var visibilityFilter = function visibilityFilter(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; | |
// This is the root reducer | |
var todoApp = combineReducers({ | |
todos: todos, | |
visibilityFilter: visibilityFilter | |
}); | |
var _React = React; | |
var Component = _React.Component; | |
// react presentational component for utilizing visibility filter | |
var Link = function Link(_ref) { | |
var active = _ref.active; | |
var children = _ref.children; | |
var onClick = _ref.onClick; | |
if (active) { | |
return React.createElement( | |
'span', | |
null, | |
children | |
); | |
} | |
return React.createElement( | |
'a', | |
{ href: '#', | |
onClick: function (e) { | |
e.preventDefault(); | |
onClick(); | |
} | |
}, | |
children | |
); | |
}; | |
// container to provide data and behavior to presentational component | |
// Renders linked based on props and Redux store state | |
var FilterLink = (function (_Component) { | |
_inherits(FilterLink, _Component); | |
function FilterLink() { | |
_classCallCheck(this, FilterLink); | |
_get(Object.getPrototypeOf(FilterLink.prototype), 'constructor', this).apply(this, arguments); | |
} | |
// Presentational component | |
_createClass(FilterLink, [{ | |
key: 'componentDidMount', | |
value: function componentDidMount() { | |
var _this = this; | |
var store = this.props.store; | |
this.unsubscribe = store.subscribe(function () { | |
return _this.forceUpdate(); | |
}); | |
} | |
}, { | |
key: 'componentWillUnmount', | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: 'render', | |
value: function render() { | |
var props = this.props; | |
var store = props.store; | |
var state = store.getState(); | |
// delegate rendering to presentational component. | |
return React.createElement( | |
Link, | |
{ | |
active: props.filter === state.visibilityFilter, | |
onClick: function () { | |
return store.dispatch({ | |
type: 'SET_VISIBILITY_FILTER', | |
filter: props.filter | |
}); | |
} | |
}, | |
props.children | |
); //return | |
} | |
}]); | |
return FilterLink; | |
})(Component); | |
var Footer = function Footer(_ref2) { | |
var store = _ref2.store; | |
return React.createElement( | |
'p', | |
null, | |
'Show:', | |
' ', | |
React.createElement( | |
FilterLink, | |
{ | |
filter: 'SHOW_ALL', | |
store: store | |
}, | |
'All' | |
), | |
', ', | |
React.createElement( | |
FilterLink, | |
{ | |
filter: 'SHOW_ACTIVE', | |
store: store | |
}, | |
'Active' | |
), | |
', ', | |
React.createElement( | |
FilterLink, | |
{ | |
filter: 'SHOW_COMPLETED', | |
store: store | |
}, | |
'Completed' | |
) | |
); | |
}; | |
// Purely presentational Todo component | |
var Todo = function Todo(_ref3) { | |
var onClick = _ref3.onClick; | |
var completed = _ref3.completed; | |
var text = _ref3.text; | |
var id = _ref3.id; | |
return React.createElement( | |
'li', | |
{ | |
onClick: onClick, | |
style: { | |
textDecoration: completed ? 'line-through' : 'none' | |
} | |
}, | |
id, | |
': ', | |
text | |
); | |
}; | |
// Purely presentational TodoList | |
var TodoList = function TodoList(_ref4) { | |
var todos = _ref4.todos; | |
var onTodoClick = _ref4.onTodoClick; | |
return React.createElement( | |
'ul', | |
null, | |
todos.map(function (todo) { | |
return React.createElement(Todo, _extends({ | |
key: todo.id | |
}, todo, { | |
onClick: function () { | |
return onTodoClick(todo.id); | |
} | |
})); | |
}) | |
); | |
}; | |
// Not really presentational or container | |
var nextTodoId = 0; | |
var AddTodo = function AddTodo(_ref5) { | |
var store = _ref5.store; | |
var input = undefined; | |
return React.createElement( | |
'div', | |
null, | |
React.createElement('input', { ref: function (node) { | |
input = node; | |
} }), | |
React.createElement( | |
'button', | |
{ onClick: function () { | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id: nextTodoId++, | |
text: input.value | |
}); | |
input.value = ''; | |
} }, | |
'Add Todo' | |
) | |
); | |
}; | |
var getVisibleTodos = function getVisibleTodos(todos, filter) { | |
switch (filter) { | |
case 'SHOW_ALL': | |
return todos; | |
case 'SHOW_COMPLETED': | |
return todos.filter(function (t) { | |
return t.completed; | |
}); | |
case 'SHOW_ACTIVE': | |
return todos.filter(function (t) { | |
return !t.completed; | |
}); | |
} | |
}; | |
// Container component. | |
// subscribes to store and rerenders todo list when store state changes | |
// calculates visible todos based on redux store state | |
// Rendering is performed by TodoList component. | |
var VisibleTodoList = (function (_Component2) { | |
_inherits(VisibleTodoList, _Component2); | |
function VisibleTodoList() { | |
_classCallCheck(this, VisibleTodoList); | |
_get(Object.getPrototypeOf(VisibleTodoList.prototype), 'constructor', this).apply(this, arguments); | |
} | |
// With the refactor of TodoList, AddTodo, and Footer, TodoApp() this is now acting as a container component. | |
_createClass(VisibleTodoList, [{ | |
key: 'componentDidMount', | |
value: function componentDidMount() { | |
var _this2 = this; | |
var store = this.props.store; | |
this.unsubscribe = store.subscribe(function () { | |
return _this2.forceUpdate(); | |
}); | |
} | |
}, { | |
key: 'componentWillUnmount', | |
value: function componentWillUnmount() { | |
this.unsubscribe(); | |
} | |
}, { | |
key: 'render', | |
value: function render() { | |
var props = this.props; | |
var store = props.store; | |
var state = store.getState(); | |
return React.createElement(TodoList, { | |
todos: getVisibleTodos(state.todos, state.visibilityFilter), | |
onTodoClick: function (id) { | |
return store.dispatch({ | |
type: 'TOGGLE_TODO', | |
id: id | |
}); | |
} | |
}); | |
} | |
}]); | |
return VisibleTodoList; | |
})(Component); | |
var TodoApp = function TodoApp(_ref6) { | |
var store = _ref6.store; | |
return React.createElement( | |
'div', | |
null, | |
React.createElement(AddTodo, { store: store }), | |
React.createElement(VisibleTodoList, { store: store }), | |
React.createElement(Footer, { store: store }) | |
); | |
}; | |
// Create store | |
var _Redux2 = Redux; | |
var createStore = _Redux2.createStore; | |
ReactDOM.render(React.createElement(TodoApp, { store: createStore(todoApp) }), document.getElementById('root')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment