-
-
Save yashikagarg13/1b50ed3ce231fd484fba1d1cf8ccc569 to your computer and use it in GitHub Desktop.
TODO App - Passing store as context using ReactRedux's Provider and creating container components using connect method source https://jsbin.com/nexumip
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> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.3/react-redux.js"></script> | |
</head> | |
<body> | |
<div id="app"></div> | |
<script id="jsbin-javascript"> | |
"use strict"; | |
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); } } | |
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 _React = React; | |
var Component = _React.Component; | |
var _ReactRedux = ReactRedux; | |
var connect = _ReactRedux.connect; | |
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 mapStateToPropsFilterLink = function mapStateToPropsFilterLink(state, ownProps) { | |
return { | |
active: ownProps.filter === state.visbilityFilter | |
}; | |
}; | |
var mapDispatchToPropsFilterLink = function mapDispatchToPropsFilterLink(dispatch, ownProps) { | |
return { | |
onClick: function onClick() { | |
dispatch({ | |
type: "SET_VISIBILITY_FILTER", | |
filter: ownProps.filter | |
}); | |
} | |
}; | |
}; | |
var FilterLink = connect(mapStateToPropsFilterLink, mapDispatchToPropsFilterLink)(Link); | |
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 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. | |
// SECOND param is context if we specify contextTypes. | |
var AddTodo = function AddTodo(_ref4) { | |
var dispatch = _ref4.dispatch; | |
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 () { | |
dispatch({ | |
type: "ADD_TODO", | |
todo: { | |
text: input.value, | |
id: ++nextTodoId | |
} | |
}); | |
input.value = ""; | |
} }, | |
"Submit" | |
) | |
); | |
}; | |
// // SPECIFYING contextTypes IS A MUST to use context feature | |
// AddTodo.contextTypes = { | |
// store: React.PropTypes.object, | |
// }; | |
AddTodo = connect()( | |
// null, // There is no need to subscribe to this store, so we are passing mapStateToProps as null | |
// null, // If we pass null or falsy value to second param, connect will pass 'dispatch' by default as prop to the component | |
// So we can go without passing any thing to conenct function | |
// if we don't want component to subscribe t store changes | |
// as well as when component only needs to access dispatch function as props. | |
AddTodo); | |
var mapStateToProps = function mapStateToProps(state) { | |
return { | |
todos: getVisibleTodos(state.todos, state.visbilityFilter) | |
}; | |
}; | |
var mapDispatchToProps = function mapDispatchToProps(dispatch) { | |
return { | |
toggleTodo: function toggleTodo(id) { | |
dispatch({ | |
type: "TOGGLE_TODO", | |
id: id | |
}); | |
} | |
}; | |
}; | |
var VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(ToDoList); | |
var TodoApp = function TodoApp() { | |
return React.createElement( | |
"div", | |
null, | |
React.createElement(AddTodo, null), | |
React.createElement(VisibleTodoList, null), | |
React.createElement(Footer, null) | |
); | |
}; | |
// class Provider extends Component { | |
// getChildContext () { | |
// return { | |
// store: this.props.store, | |
// }; | |
// } | |
// render () { | |
// return this.props.children; | |
// } | |
// } | |
// // SPECIFYING childContextTypes IS A MUST to use context feature | |
// Provider.childContextTypes = { | |
// store: React.PropTypes.object, | |
// }; | |
var _Redux2 = Redux; | |
var createStore = _Redux2.createStore; | |
var _ReactRedux2 = ReactRedux; | |
var Provider = _ReactRedux2.Provider; | |
ReactDOM.render(React.createElement( | |
Provider, | |
{ store: createStore(todoAppReducer) }, | |
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 {Component} = React; | |
const {connect} = ReactRedux; | |
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> | |
}; | |
const mapStateToPropsFilterLink = (state, ownProps) => { | |
return { | |
active: ownProps.filter === state.visbilityFilter, | |
}; | |
} | |
const mapDispatchToPropsFilterLink = (dispatch, ownProps) => { | |
return { | |
onClick: () => { | |
dispatch({ | |
type: "SET_VISIBILITY_FILTER", | |
filter: ownProps.filter | |
}) | |
} | |
}; | |
} | |
const FilterLink = connect( | |
mapStateToPropsFilterLink, | |
mapDispatchToPropsFilterLink, | |
)(Link); | |
const Footer = () => { | |
return ( | |
<p>Show: | |
<FilterLink filter="SHOW_ALL"> | |
All</FilterLink> | |
<FilterLink filter="SHOW_ACTIVE"> | |
Active</FilterLink> | |
<FilterLink filter="SHOW_COMPLETED"> | |
Completed</FilterLink> | |
</p> | |
); | |
} | |
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. | |
// SECOND param is context if we specify contextTypes. | |
let AddTodo = ({dispatch}) => { | |
let input; | |
return ( | |
<div> | |
<input type="text" ref={node => {input = node;}} /> | |
<button type="button" | |
onClick={() => { | |
dispatch({ | |
type: "ADD_TODO", | |
todo: { | |
text: input.value, | |
id: ++nextTodoId | |
} | |
}); | |
input.value = ""; | |
}}>Submit</button> | |
</div> | |
); | |
} | |
// // SPECIFYING contextTypes IS A MUST to use context feature | |
// AddTodo.contextTypes = { | |
// store: React.PropTypes.object, | |
// }; | |
AddTodo = connect( | |
// null, // There is no need to subscribe to this store, so we are passing mapStateToProps as null | |
// null, // If we pass null or falsy value to second param, connect will pass 'dispatch' by default as prop to the component | |
// So we can go without passing any thing to conenct function | |
// if we don't want component to subscribe t store changes | |
// as well as when component only needs to access dispatch function as props. | |
)(AddTodo); | |
const mapStateToProps = (state) => { | |
return { | |
todos: getVisibleTodos(state.todos, state.visbilityFilter), | |
}; | |
} | |
const mapDispatchToProps = (dispatch) => { | |
return { | |
toggleTodo: id => { | |
dispatch({ | |
type: "TOGGLE_TODO", | |
id, | |
}); | |
} | |
}; | |
} | |
const VisibleTodoList = connect( | |
mapStateToProps, | |
mapDispatchToProps, | |
)(ToDoList); | |
const TodoApp = () => { | |
return ( | |
<div> | |
<AddTodo /> | |
<VisibleTodoList /> | |
<Footer /> | |
</div> | |
); | |
} | |
// class Provider extends Component { | |
// getChildContext () { | |
// return { | |
// store: this.props.store, | |
// }; | |
// } | |
// render () { | |
// return this.props.children; | |
// } | |
// } | |
// // SPECIFYING childContextTypes IS A MUST to use context feature | |
// Provider.childContextTypes = { | |
// store: React.PropTypes.object, | |
// }; | |
const {createStore} = Redux; | |
const {Provider} = ReactRedux; | |
ReactDOM.render( | |
<Provider store={createStore(todoAppReducer)}> | |
<TodoApp/> | |
</Provider>, | |
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 _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); } } | |
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 _React = React; | |
var Component = _React.Component; | |
var _ReactRedux = ReactRedux; | |
var connect = _ReactRedux.connect; | |
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 mapStateToPropsFilterLink = function mapStateToPropsFilterLink(state, ownProps) { | |
return { | |
active: ownProps.filter === state.visbilityFilter | |
}; | |
}; | |
var mapDispatchToPropsFilterLink = function mapDispatchToPropsFilterLink(dispatch, ownProps) { | |
return { | |
onClick: function onClick() { | |
dispatch({ | |
type: "SET_VISIBILITY_FILTER", | |
filter: ownProps.filter | |
}); | |
} | |
}; | |
}; | |
var FilterLink = connect(mapStateToPropsFilterLink, mapDispatchToPropsFilterLink)(Link); | |
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 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. | |
// SECOND param is context if we specify contextTypes. | |
var AddTodo = function AddTodo(_ref4) { | |
var dispatch = _ref4.dispatch; | |
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 () { | |
dispatch({ | |
type: "ADD_TODO", | |
todo: { | |
text: input.value, | |
id: ++nextTodoId | |
} | |
}); | |
input.value = ""; | |
} }, | |
"Submit" | |
) | |
); | |
}; | |
// // SPECIFYING contextTypes IS A MUST to use context feature | |
// AddTodo.contextTypes = { | |
// store: React.PropTypes.object, | |
// }; | |
AddTodo = connect()( | |
// null, // There is no need to subscribe to this store, so we are passing mapStateToProps as null | |
// null, // If we pass null or falsy value to second param, connect will pass 'dispatch' by default as prop to the component | |
// So we can go without passing any thing to conenct function | |
// if we don't want component to subscribe t store changes | |
// as well as when component only needs to access dispatch function as props. | |
AddTodo); | |
var mapStateToProps = function mapStateToProps(state) { | |
return { | |
todos: getVisibleTodos(state.todos, state.visbilityFilter) | |
}; | |
}; | |
var mapDispatchToProps = function mapDispatchToProps(dispatch) { | |
return { | |
toggleTodo: function toggleTodo(id) { | |
dispatch({ | |
type: "TOGGLE_TODO", | |
id: id | |
}); | |
} | |
}; | |
}; | |
var VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(ToDoList); | |
var TodoApp = function TodoApp() { | |
return React.createElement( | |
"div", | |
null, | |
React.createElement(AddTodo, null), | |
React.createElement(VisibleTodoList, null), | |
React.createElement(Footer, null) | |
); | |
}; | |
// class Provider extends Component { | |
// getChildContext () { | |
// return { | |
// store: this.props.store, | |
// }; | |
// } | |
// render () { | |
// return this.props.children; | |
// } | |
// } | |
// // SPECIFYING childContextTypes IS A MUST to use context feature | |
// Provider.childContextTypes = { | |
// store: React.PropTypes.object, | |
// }; | |
var _Redux2 = Redux; | |
var createStore = _Redux2.createStore; | |
var _ReactRedux2 = ReactRedux; | |
var Provider = _ReactRedux2.Provider; | |
ReactDOM.render(React.createElement( | |
Provider, | |
{ store: createStore(todoAppReducer) }, | |
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