[Redux] Extracting Container Components -- VisibleTodoList
Code to be refacted:
const TodoList = ({
todos,
onTodoClick
}) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
);
let nextTodoId = 0;
const TodoApp = ({
todos,
visibilityFilter
}) => (
<div>
...
...
<TodoList
todos={
getVisibleTodos(
todos,
visibilityFilter
)
}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
....
</div>
);
Currently we pass the 'todos' and 'onTodoClick' from top container component 'TodoApp', all the way down to the 'Todo' component.
So we want simplfy 'TodoList' Component in TodoApp, create a new container component 'VisibleTodoList'.
In TodoApp:
const TodoApp = ({
todos,
visibilityFilter
}) => (
<div>
<AddTodo
onAddClick={text =>
store.dispatch({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
}
/>
<VisibleTodoList />
<Footer />
</div>
);
VisibleTodoList:
class VisibleTodoList extends Component {
componentDidMount() {
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const props = this.props;
const state = store.getState();
return (
<TodoList
todos={
getVisibleTodos(
state.todos,
state.visibilityFilter
)
}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
);
}
}
----------------
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;
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() {
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const props = this.props;
const state = store.getState();
return (
<Link
active={
props.filter ===
state.visibilityFilter
}
onClick={() =>
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: props.filter
})
}
>
{props.children}
</Link>
);
}
}
const Footer = () => (
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
>
All
</FilterLink>
{', '}
<FilterLink
filter='SHOW_ACTIVE'
>
Active
</FilterLink>
{', '}
<FilterLink
filter='SHOW_COMPLETED'
>
Completed
</FilterLink>
</p>
);
const Todo = ({
onClick,
completed,
text
}) => (
<li
onClick={onClick}
style={{
textDecoration:
completed ?
'line-through' :
'none'
}}
>
{text}
</li>
);
const TodoList = ({
todos,
onTodoClick
}) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
);
const AddTodo = ({
onAddClick
}) => {
let input;
return (
<div>
<input ref={node => {
input = node;
}} />
<button onClick={() => {
onAddClick(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
);
}
}
class VisibleTodoList extends Component {
componentDidMount() {
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const props = this.props;
const state = store.getState();
return (
<TodoList
todos={
getVisibleTodos(
state.todos,
state.visibilityFilter
)
}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
);
}
}
let nextTodoId = 0;
const TodoApp = ({
todos,
visibilityFilter
}) => (
<div>
<AddTodo
onAddClick={text =>
store.dispatch({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
}
/>
<VisibleTodoList />
<Footer />
</div>
);
const render = () => {
ReactDOM.render(
<TodoApp
{...store.getState()}
/>,
document.getElementById('root')
);
};
store.subscribe(render);
render();
[Redux] Extracting Container Components -- VisibleTodoList的更多相关文章
- [Redux] Extracting Container Components (FilterLink)
Learn how to avoid the boilerplate of passing the props down the intermediate components by introduc ...
- [Redux] Extracting Container Components -- Complete
Clean TodoApp Component, it doesn't need to receive any props from the top level component: const To ...
- [Redux] Redux: Extracting Container Components -- AddTodo
Code to be refactored: const AddTodo = ({ onAddClick }) => { let input; return ( <div> < ...
- [Redux] Extracting Presentational Components -- AddTodo
The code to be refactored: let nextTodoId = 0; class TodoApp extends Component { render() { const { ...
- [Redux] Extracting Presentational Components -- Footer, FilterLink
Code to be refactored: let nextTodoId = 0; class TodoApp extends Component { render() { const { todo ...
- [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 ...
- [Redux] Extracting Presentational Components -- Todo, TodoList
Code to be refactored: let nextTodoId = 0; class TodoApp extends Component { render() { const { todo ...
- Presentational and Container Components
https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 There’s a simple pattern I fi ...
- (翻译)React Container Components
原文:Container Components Container Components 在 React 模式上对我的代码有最深远影响的一个模式叫 container component 模式. 在 ...
随机推荐
- java开发webservice的几种方式
webservice的应用已经越来越广泛了,下面介绍几种在Java体系中开发webservice的方式,相当于做个记录. 1.Axis2 Axis是apache下一个开源的webservice开发组件 ...
- mybatis之特殊查询
在mybatis查询的过程中,某个字段是经过计算得到的,这时,在设计数据表的时候,就不 必在增加此对应的字段 那么,在查询的时候,页面有需要展示这个字段时,怎么办呢? 举个例子: 在查询微信团商品时, ...
- java基础学习----String
旨在从内存方面看String类的知识点: 1.为何不能被继承(final类) 2.字符拼接时,String类的内存分配问题. 3.String的intern()方法 关于String类经常出现的面试题 ...
- Arduino 板子 COM 接口找不到设备
复位 Arduino 板子 1.打开官方的blink程序. 2.重新拔插usb. 3.点下载. 4.按住左上角的复位按键不放. 5.等显示开始下载瞬间松开按键.把握住那个瞬间. 6.多试验几次看能 ...
- pubwin数据云备份
由于pubwin自带的异地备份一直不好用,并且pubwin自带的37分钟备份也不方便手动备份,考虑用python 与写一个基于酷盘的pubwin数据备份工具(本来想基于百度云的,发现百度云用的人太多, ...
- DOMElement之Offset
有明确目的的学习比较有效,我学习HTML offset相关概念是出自一个需求,那就是计算一个绝对定位的HTML元素相对于当前窗口的偏移距离,主要是Y方向的偏移,X方向同理. 要实现这个目的,首先要弄清 ...
- Adt 配置注释模板
点击Window->Preferences->Java->Code Style->Code Templates,如下图所示: 选中,点击右侧的Edit进行编辑.
- 有关WCF的契约问题
WCF中的契约包括4种 数据契约 DataContract ->DataMember 服务契约 ServiceContract-> OperactionContract 消息契约 Mess ...
- HTTP methods 与 RESTful API
Note GET, primarily used to select resources. Other options for an API method include: POST, primari ...
- BZOJ2045: 双亲数
2045: 双亲数 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 602 Solved: 275[Submit][Status] Descripti ...