React Todo List Example (Filtering Todos)
Will dispatch the SET_VISIBILITY_FILTER action.
const { Component } = React;
// ++++ crate FilterLink React component
const FilterLink = ({filter, children}) => {
return <a href="#" onClick = {e => {
e.preventDefault();
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
});
}}>
{children}
</a>
}
let nextTodoId = 0;
class TodoApp extends Component {
render() {
// ++++ get the visible todos
const visibleTodos = getVisibleTodos(
this.props.todos,
this.props.visibilityFilter
)
return (
<div>
<input .../>
<button onClick={() => {...}</button>
<ul>
// ++-- change here to visible todos
// {this.props.todos.map(todo => {...}
{visibleTodos.todos.map(todo => {...}
</ul>
// ++++
<p>
Show:
{' '}
<FilterLink filter='SHOW_ALL'>All</FilterLink>
{' '}
<FilterLink filter='SHOW_ACTIVE'>Active</FilterLink>
{' '}
<FilterLink filter='SHOW_COMPLETED'>Completed</FilterLink>
{' '}
</p>
</div>
)
}
}
// ++++ add todo filter function
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
)
}
}
const render = () => {
ReactDOM.render(
// ++-- pass all state fields to the rendering
<TodoApp {...store.getState()} />,
document.getElementById('root');
)
};
store.subscribe(render);
render();
Next step: highlight the chosen (active) visibility link selector in the UI
const { Component } = React;
// ++++ add currentFilter argument
const FilterLink = ({filter, currentFilter, children}) => {
// ++++
if (filter === currentFilter) {
// return a span instead of a link (selected vfilter)
return <span>{children}</span>;
}
return <a href="#" onClick = {e => {
e.preventDefault();
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
});
}}>
{children}
</a>
}
let nextTodoId = 0;
class TodoApp extends Component {
render() {
// ++++ destructuring
const {
todos,
visibilityFilter
} = this.props;
const visibleTodos = getVisibleTodos(
// ++-- thanks to destructuring
// we can access them directly
todos,
visibilityFilter
)
return (
<div>
<input .../>
<button onClick={() => {...}</button>
<ul>
{visibleTodos.todos.map(todo => {...}
</ul>
<p>
Show:
{' '}
// add currentFilter to each FilterLink
<FilterLink
filter='SHOW_ALL'
currentFilter={visibilityFilter}
>All</FilterLink>
{' '}
<FilterLink
filter='SHOW_ACTIVE'
currentFilter={visibilityFilter}
>Active</FilterLink>
{' '}
<FilterLink
filter='SHOW_COMPLETED'
currentFilter={visibilityFilter}
>Completed</FilterLink>
{' '}
</p>
</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
)
}
}
const render = () => {
ReactDOM.render(
<TodoApp {...store.getState()} />,
document.getElementById('root');
)
};
store.subscribe(render);
render();