Code to be refactored:

let nextTodoId = 0;
class TodoApp extends Component {
render() {
const {
todos,
visibilityFilter
} = this.props;
const visibleTodos = getVisibleTodos(
todos,
visibilityFilter
);
return (
<div>
<input ref={node => {
this.input = node;
}} />
<button onClick={() => {
store.dispatch({
type: 'ADD_TODO',
text: this.input.value,
id: nextTodoId++
});
this.input.value = '';
}}>
Add Todo
</button>
<ul>
{visibleTodos.map(todo =>
<li key={todo.id}
onClick={() => {
store.dispatch({
type: 'TOGGLE_TODO',
id: todo.id
});
}}
style={{
textDecoration:
todo.completed ?
'line-through' :
'none'
}}>
{todo.text}
</li>
)}
</ul>
<p>
Show:
{' '}
<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 FilterLink = ({
filter,
currentFilter,
children
}) => {
if (filter === currentFilter) {
return <span>{children}</span>;
} return (
<a href='#'
onClick={e => {
e.preventDefault();
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
});
}}
>
{children}
</a>
);
};

Refactor footer part into a functional component, which contains all these three filter links. Pass in visibilityFilter as props:

const Footer = ({
visibilityFilter
}) => (
<p>
Show:
{' '}
<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>
);

In the FilterLink,  we want it to be presentational components. However, the filter link includes a short dispatch call. I am replacing it with an on click call. I pass the filter as the single parameter for the calling component's convenience. I add on click to the props.

const FilterLink = ({
filter,
currentFilter,
children,
onFilterClick
}) => {
if (filter === currentFilter) {
return <span>{children}</span>;
} return (
<a href='#'
onClick={e => {
e.preventDefault();
onFilterClick(filter);
}}
>
{children}
</a>
);
};
const Footer = ({
visibilityFilter,
onFilterClick
}) => (
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
currentFilter={visibilityFilter}
onFilterClick={onFilterClick}
>
All
</FilterLink>
{', '}
<FilterLink
filter='SHOW_ACTIVE'
currentFilter={visibilityFilter}
onFilterClick={onFilterClick}
>
Active
</FilterLink>
{', '}
<FilterLink
filter='SHOW_COMPLETED'
currentFilter={visibilityFilter}
onFilterClick={onFilterClick}
>
Completed
</FilterLink>
</p>
);

-----------------------------------

Code:

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;
}
}; 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 { combineReducers } = Redux;
const todoApp = combineReducers({
todos,
visibilityFilter
}); const { createStore } = Redux;
const store = createStore(todoApp); const { Component } = React; /**
Functional compoment, persental compoment: doesn't need to know what to do, just show the interface, call the callback function.
*/
const AddTodo = ({
onAddTodo
}) => { let input;
return (
<div>
<input ref={node => {
input = node;
}} />
<button onClick={() => {
onAddTodo(input.value);
input.value = '';
}}>
Add Todo
</button>
</div>
);
} /* Functional component */
const Footer = ({
visibilityFilter,
onFilterClick
}) => (
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
currentFilter={visibilityFilter}
onFilterClick={onFilterClick}
>
All
</FilterLink>
{', '}
<FilterLink
filter='SHOW_ACTIVE'
currentFilter={visibilityFilter}
onFilterClick={onFilterClick}
>
Active
</FilterLink>
{', '}
<FilterLink
filter='SHOW_COMPLETED'
currentFilter={visibilityFilter}
onFilterClick={onFilterClick}
>
Completed
</FilterLink>
</p>
); const FilterLink = ({
filter,
currentFilter,
children,
onFilterClick
}) => {
if (filter === currentFilter) {
return <span>{children}</span>;
} return (
<a href='#'
onClick={e => {
e.preventDefault();
onFilterClick(filter);
}}
>
{children}
</a>
);
}; 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
);
}
} let nextTodoId = 0;
class TodoApp extends Component {
render() {
const {
todos,
visibilityFilter
} = this.props;
const visibleTodos = getVisibleTodos(
todos,
visibilityFilter
);
return (
<div>
<AddTodo
onAddTodo={ text =>
store.dispatch({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
}
/>
<ul>
{visibleTodos.map(todo =>
<li key={todo.id}
onClick={() => {
store.dispatch({
type: 'TOGGLE_TODO',
id: todo.id
});
}}
style={{
textDecoration:
todo.completed ?
'line-through' :
'none'
}}>
{todo.text}
</li>
)}
</ul>
<Footer
visibilityFilter = {visibilityFilter}
onFilterClick={ (filter) => {
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
});
}}
/>
</div>
);
}
} const render = () => {
ReactDOM.render(
<TodoApp
{...store.getState()}
/>,
document.getElementById('root')
);
}; store.subscribe(render);
render();

[Redux] Extracting Presentational Components -- Footer, FilterLink的更多相关文章

  1. [Redux] Extracting Presentational Components -- AddTodo

    The code to be refactored: let nextTodoId = 0; class TodoApp extends Component { render() { const { ...

  2. [Redux] Extracting Presentational Components -- TodoApp

    Finally, I just noticed that the to-do app component doesn't actually have to be a class. I can turn ...

  3. [Redux] Extracting Presentational Components -- Todo, TodoList

    Code to be refactored: let nextTodoId = 0; class TodoApp extends Component { render() { const { todo ...

  4. [Redux] Extracting Container Components -- Complete

    Clean TodoApp Component, it doesn't need to receive any props from the top level component: const To ...

  5. [Redux] Extracting Container Components (FilterLink)

    Learn how to avoid the boilerplate of passing the props down the intermediate components by introduc ...

  6. [Redux] Redux: Extracting Container Components -- AddTodo

    Code to be refactored: const AddTodo = ({ onAddClick }) => { let input; return ( <div> < ...

  7. [Redux] Extracting Container Components -- VisibleTodoList

    Code to be refacted: const TodoList = ({ todos, onTodoClick }) => ( <ul> {todos.map(todo =& ...

  8. [Redux] Extracting Action Creators

    We will create an anction creator to manage the dispatch actions, to keep code maintainable and self ...

  9. Presentational and Container Components

    https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 There’s a simple pattern I fi ...

随机推荐

  1. com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException idea 导出war 报错

    com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException 部署到in ...

  2. OD: GS Bypasing via SEH / .data

    通过 SEH 绕过 GS 保护 GS 机制没对 SEH 提供保护,所以可心通过攻击异常来绕过 GS. 实验环境为: VMware : Windows sp4, 此版本无 SafeSEH 的影响 Vis ...

  3. HTML基础总结<链接>

    HTML 超链接(链接) HTML使用标签 <a>来设置超文本链接. 超链接可以是一个字,一个词,或者一组词,也可以是一幅图像,您可以点击这些内容来跳转到新的文档或者当前文档中的某个部分. ...

  4. Sass变量、嵌套

    声明变量定义变量的语法Sass 的变量包括三个部分: 声明变量的符号“$” 变量名称 赋予变量的值简单的示例,假设你的按钮颜色可以给其声明几个变量: $brand-primary : darken(# ...

  5. cocos2dx 帧动画(iOS)

    植物大战僵尸的植物摇摆效果 //帧动画 Animation *animation = Animation::create(); Sprite *sprite = Sprite::create(&quo ...

  6. iOS分享 - AFNetworking之多图片/文件上传

    在分享经验之前,先说点题外话,之前的一个项目涉及到了多图片的上传,本来以为是一个很简单的事情,却着实困扰了我好久,究其原因,一是我不够细心,二是与后台人员的交流不够充分.在此,我想将我的老师常说的一句 ...

  7. Spring MVC 之 Hello World

    1.新建一个动态web项目 2.web.xml编写 <?xml version="1.0" encoding="UTF-8"?> <web-a ...

  8. 【转】C++成员函数的存储方式

    [转] http://c.biancheng.net/cpp/biancheng/view/187.html 用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据 ...

  9. mysql 简单的增删改查语句

    增加记录: 注:null关键字与auto_increment限制条件相结合,可以为字段自动赋值:字段必须全,且一一对应:字符型用单引号: mysql> insert into test valu ...

  10. python学习第十五天 -面向对象之继承和多态

    大家都知道面向对象的三大特性:封装,继承,多态.封装特性在上一章节已经讲解过.这一章节主要讲解继承和多态. 继承: 当定义一个类的时候,可以从现有的类进行继承.那么新定义的类可以称为子类,被继承的现有 ...