Skip to content

Instantly share code, notes, and snippets.

@cakiem8x
Created November 30, 2017 14:14
Show Gist options
  • Save cakiem8x/c4ed923f1c380e294d815db374d379be to your computer and use it in GitHub Desktop.
Save cakiem8x/c4ed923f1c380e294d815db374d379be to your computer and use it in GitHub Desktop.
JS Bin // source https://jsbin.com/futowin
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://fb.me/react-15.1.0.js"></script>
<script src="https://fb.me/react-dom-15.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect/1.20.2/expect.min.js"></script>
</head>
<body>
<div id="root"></div>
<script id="jsbin-javascript">
const todo = (state, action) => {
switch (action.type) {
case 'TOGGLE_TODO':
if (state.id !== action.id)
return state;
return {
...state,
completed: !state.completed
};
case 'ADD_TODO':
return action.payload;
default:
return state;
}
}
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
todo(undefined, action)
];
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 {Component} = React;
const todoApp = combineReducers({
todos,
visibilityFilter
})
const Style = {
complete: {
textDecoration: 'line-through'
}
};
const Link = ({
active,
children,
onClick
}) => {
if (active) {
return <span>{children}</span>
}
return (
<a
href="#"
onClick={(e) => {
e.preventDefault();
onClick();
}}
>
{children}
</a>
)
}
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();
return (
<Link
active={props.filter === state.visibilityFilter}
onClick={() => {
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
props.filter
})
}}
>
{props.children}
</link>
)
}
}
const Todo = ({
onClick,
completed,
text
}) => {
return <li
onClick={onClick}
style={completed ? Style.complete : {}}
>
{text}
</li>
}
const getVisiableTodos = (
todos,
visibilityFilter
) => {
switch (visibilityFilter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_ACTIVE':
return todos.filter(
t => !t.completed
);
case 'SHOW_COMPLETED':
return todos.filter(
t => t.completed
);
}
}
let nextTodoId = 0;
const AddTodo = ({
store
}) => {
let input;
return <div>
<input
ref={node => {
input = node;
}}/>
<button
onClick={() => {
store.dispatch({
type: 'ADD_TODO',
payload: {
id: nextTodoId++,
text: input.value,
completed: false
}
})
input.value = '';
}}
>
Add Todo
</button>
</div>
}
const Footer = ({
store
}) => (
<p>
Show:
{' '}
<FilterLink
filter="SHOW_ALL"
store={store}
>
All
</Link>
{' '}
<FilterLink
filter="SHOW_ACTIVE"
store={store}
>
Active
</Link>
{' '}
<FilterLink
filter="SHOW_COMPLETED"
store={store}
>
Completed
</Link>
</p>
)
const TodoList = ({
todos,
onTodoClick
}) => {
return <ul>
{todos.map(todo =>
<Todo
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
}
class VisiableTodoList 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={
getVisiableTodo(
state.todos,
state.visibilityFilter
)
}
onTodoClick={id => {
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
);
}
}
const TodoApp = ({
store
}) => (
<div>
<AddTodo store={store} />
<VisiableTodoList store={store} />
<Footer store={store} />
</div>
)
const {createStore, combineReducers} = Redux
ReactDOM.render(
<TodoApp store={createStore(todoApp)} />,
document.getElementById('root')
)
</script>
<script id="jsbin-source-javascript" type="text/javascript">const todo = (state, action) => {
switch (action.type) {
case 'TOGGLE_TODO':
if (state.id !== action.id)
return state;
return {
...state,
completed: !state.completed
};
case 'ADD_TODO':
return action.payload;
default:
return state;
}
}
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
todo(undefined, action)
];
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 {Component} = React;
const todoApp = combineReducers({
todos,
visibilityFilter
})
const Style = {
complete: {
textDecoration: 'line-through'
}
};
const Link = ({
active,
children,
onClick
}) => {
if (active) {
return <span>{children}</span>
}
return (
<a
href="#"
onClick={(e) => {
e.preventDefault();
onClick();
}}
>
{children}
</a>
)
}
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();
return (
<Link
active={props.filter === state.visibilityFilter}
onClick={() => {
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
props.filter
})
}}
>
{props.children}
</link>
)
}
}
const Todo = ({
onClick,
completed,
text
}) => {
return <li
onClick={onClick}
style={completed ? Style.complete : {}}
>
{text}
</li>
}
const getVisiableTodos = (
todos,
visibilityFilter
) => {
switch (visibilityFilter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_ACTIVE':
return todos.filter(
t => !t.completed
);
case 'SHOW_COMPLETED':
return todos.filter(
t => t.completed
);
}
}
let nextTodoId = 0;
const AddTodo = ({
store
}) => {
let input;
return <div>
<input
ref={node => {
input = node;
}}/>
<button
onClick={() => {
store.dispatch({
type: 'ADD_TODO',
payload: {
id: nextTodoId++,
text: input.value,
completed: false
}
})
input.value = '';
}}
>
Add Todo
</button>
</div>
}
const Footer = ({
store
}) => (
<p>
Show:
{' '}
<FilterLink
filter="SHOW_ALL"
store={store}
>
All
</Link>
{' '}
<FilterLink
filter="SHOW_ACTIVE"
store={store}
>
Active
</Link>
{' '}
<FilterLink
filter="SHOW_COMPLETED"
store={store}
>
Completed
</Link>
</p>
)
const TodoList = ({
todos,
onTodoClick
}) => {
return <ul>
{todos.map(todo =>
<Todo
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
}
class VisiableTodoList 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={
getVisiableTodo(
state.todos,
state.visibilityFilter
)
}
onTodoClick={id => {
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
);
}
}
const TodoApp = ({
store
}) => (
<div>
<AddTodo store={store} />
<VisiableTodoList store={store} />
<Footer store={store} />
</div>
)
const {createStore, combineReducers} = Redux
ReactDOM.render(
<TodoApp store={createStore(todoApp)} />,
document.getElementById('root')
)</script></body>
</html>
const todo = (state, action) => {
switch (action.type) {
case 'TOGGLE_TODO':
if (state.id !== action.id)
return state;
return {
...state,
completed: !state.completed
};
case 'ADD_TODO':
return action.payload;
default:
return state;
}
}
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
todo(undefined, action)
];
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 {Component} = React;
const todoApp = combineReducers({
todos,
visibilityFilter
})
const Style = {
complete: {
textDecoration: 'line-through'
}
};
const Link = ({
active,
children,
onClick
}) => {
if (active) {
return <span>{children}</span>
}
return (
<a
href="#"
onClick={(e) => {
e.preventDefault();
onClick();
}}
>
{children}
</a>
)
}
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();
return (
<Link
active={props.filter === state.visibilityFilter}
onClick={() => {
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
props.filter
})
}}
>
{props.children}
</link>
)
}
}
const Todo = ({
onClick,
completed,
text
}) => {
return <li
onClick={onClick}
style={completed ? Style.complete : {}}
>
{text}
</li>
}
const getVisiableTodos = (
todos,
visibilityFilter
) => {
switch (visibilityFilter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_ACTIVE':
return todos.filter(
t => !t.completed
);
case 'SHOW_COMPLETED':
return todos.filter(
t => t.completed
);
}
}
let nextTodoId = 0;
const AddTodo = ({
store
}) => {
let input;
return <div>
<input
ref={node => {
input = node;
}}/>
<button
onClick={() => {
store.dispatch({
type: 'ADD_TODO',
payload: {
id: nextTodoId++,
text: input.value,
completed: false
}
})
input.value = '';
}}
>
Add Todo
</button>
</div>
}
const Footer = ({
store
}) => (
<p>
Show:
{' '}
<FilterLink
filter="SHOW_ALL"
store={store}
>
All
</Link>
{' '}
<FilterLink
filter="SHOW_ACTIVE"
store={store}
>
Active
</Link>
{' '}
<FilterLink
filter="SHOW_COMPLETED"
store={store}
>
Completed
</Link>
</p>
)
const TodoList = ({
todos,
onTodoClick
}) => {
return <ul>
{todos.map(todo =>
<Todo
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
}
class VisiableTodoList 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={
getVisiableTodo(
state.todos,
state.visibilityFilter
)
}
onTodoClick={id => {
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
);
}
}
const TodoApp = ({
store
}) => (
<div>
<AddTodo store={store} />
<VisiableTodoList store={store} />
<Footer store={store} />
</div>
)
const {createStore, combineReducers} = Redux
ReactDOM.render(
<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