Code to be refactored:

  1. class FilterLink extends Component {
  2. componentDidMount() {
  3. const { store } = this.context;
  4. this.unsubscribe = store.subscribe(() =>
  5. this.forceUpdate()
  6. );
  7. }
  8.  
  9. componentWillUnmount() {
  10. this.unsubscribe();
  11. }
  12.  
  13. render() {
  14. const props = this.props;
  15. const { store } = this.context;
  16. const state = store.getState();
  17.  
  18. return (
  19. <Link
  20. active={
  21. props.filter ===
  22. state.visibilityFilter
  23. }
  24. onClick={() =>
  25. store.dispatch({
  26. type: 'SET_VISIBILITY_FILTER',
  27. filter: props.filter
  28. })
  29. }
  30. >
  31. {props.children}
  32. </Link>
  33. );
  34. }
  35. }
  36. FilterLink.contextTypes = {
  37. store: React.PropTypes.object
  38. };

First to create mapStateToProps, It is fairly common to use the container props when calculating the child props, so this is why props are passed as a second argument:

  1. const mapStateToLinkProps = (
  2. state,
  3. ownProps
  4. ) => {
  5. return {
  6. active: ownProps.filter === state.visibilityFilter
  7. }
  8. }

Second, we need to write mapDispatchToProp function:

  1. const mapDispatchToLinkProps = (
  2. dispatch,
  3. ownProps
  4. ) => {
  5. return {
  6. onClick: () => {
  7. dispatch({
  8. type: 'SET_VISIBILITY_FILTER',
  9. filter: ownProps.filter
  10. })
  11. }
  12. }
  13. }

Last, we need to create connect function, point to the Link compoment:

  1. const FilterLink = connect(mapStateToLinkProps, mapDispatchToLinkProps)(Link);

We can now use the filter link container component and specify just the filter, but the underlying link component will have received the calculated active and on-click values.

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

Code:

  1. const todo = (state, action) => {
  2. switch (action.type) {
  3. case 'ADD_TODO':
  4. return {
  5. id: action.id,
  6. text: action.text,
  7. completed: false
  8. };
  9. case 'TOGGLE_TODO':
  10. if (state.id !== action.id) {
  11. return state;
  12. }
  13.  
  14. return {
  15. ...state,
  16. completed: !state.completed
  17. };
  18. default:
  19. return state;
  20. }
  21. };
  22.  
  23. const todos = (state = [], action) => {
  24. switch (action.type) {
  25. case 'ADD_TODO':
  26. return [
  27. ...state,
  28. todo(undefined, action)
  29. ];
  30. case 'TOGGLE_TODO':
  31. return state.map(t =>
  32. todo(t, action)
  33. );
  34. default:
  35. return state;
  36. }
  37. };
  38.  
  39. const visibilityFilter = (
  40. state = 'SHOW_ALL',
  41. action
  42. ) => {
  43. switch (action.type) {
  44. case 'SET_VISIBILITY_FILTER':
  45. return action.filter;
  46. default:
  47. return state;
  48. }
  49. };
  50.  
  51. const { combineReducers } = Redux;
  52. const todoApp = combineReducers({
  53. todos,
  54. visibilityFilter
  55. });
  56.  
  57. const { Component } = React;
  58.  
  59. const Link = ({
  60. active,
  61. onClick,
  62. children,
  63. }) => {
  64. if (active) {
  65. return <span>{children}</span>;
  66. }
  67.  
  68. return (
  69. <a href='#'
  70. onClick={e => {
  71. e.preventDefault();
  72. onClick();
  73. }}
  74. >
  75. {children}
  76. </a>
  77. );
  78. };
  79.  
  80. const { connect } = ReactRedux;
  81. const mapStateToLinkProps = (
  82. state,
  83. ownProps
  84. ) => {
  85. return {
  86. active: ownProps.filter === state.visibilityFilter
  87. }
  88. }
  89.  
  90. const mapDispatchToLinkProps = (
  91. dispatch,
  92. ownProps
  93. ) => {
  94. return {
  95. onClick: () => {
  96. dispatch({
  97. type: 'SET_VISIBILITY_FILTER',
  98. filter: ownProps.filter
  99. })
  100. }
  101. }
  102. }
  103.  
  104. const FilterLink = connect(mapStateToLinkProps, mapDispatchToLinkProps)(Link);
  105.  
  106. const Footer = () => (
  107. <p>
  108. Show:
  109. {' '}
  110. <FilterLink filter='SHOW_ALL'>
  111. All
  112. </FilterLink>
  113. {', '}
  114. <FilterLink filter='SHOW_ACTIVE'>
  115. Active
  116. </FilterLink>
  117. {', '}
  118. <FilterLink filter='SHOW_COMPLETED'>
  119. Completed
  120. </FilterLink>
  121. </p>
  122. );
  123.  
  124. const Todo = ({
  125. onClick,
  126. completed,
  127. text
  128. }) => (
  129. <li
  130. onClick={onClick}
  131. style={{
  132. textDecoration:
  133. completed ?
  134. 'line-through' :
  135. 'none'
  136. }}
  137. >
  138. {text}
  139. </li>
  140. );
  141.  
  142. const TodoList = ({
  143. todos,
  144. onTodoClick
  145. }) => (
  146. <ul>
  147. {todos.map(todo =>
  148. <Todo
  149. key={todo.id}
  150. {...todo}
  151. onClick={() => onTodoClick(todo.id)}
  152. />
  153. )}
  154. </ul>
  155. );
  156.  
  157. let nextTodoId = 0;
  158. let AddTodo = ({ dispatch }) => {
  159. let input;
  160.  
  161. return (
  162. <div>
  163. <input ref={node => {
  164. input = node;
  165. }} />
  166. <button onClick={() => {
  167. dispatch({
  168. type: 'ADD_TODO',
  169. id: nextTodoId++,
  170. text: input.value
  171. })
  172. input.value = '';
  173. }}>
  174. Add Todo
  175. </button>
  176. </div>
  177. );
  178. };
  179. AddTodo = connect()(AddTodo);
  180.  
  181. const getVisibleTodos = (
  182. todos,
  183. filter
  184. ) => {
  185. switch (filter) {
  186. case 'SHOW_ALL':
  187. return todos;
  188. case 'SHOW_COMPLETED':
  189. return todos.filter(
  190. t => t.completed
  191. );
  192. case 'SHOW_ACTIVE':
  193. return todos.filter(
  194. t => !t.completed
  195. );
  196. }
  197. }
  198.  
  199. const mapStateToTodoListProps = (state) => {
  200. return {
  201. todos: getVisibleTodos(
  202. state.todos,
  203. state.visibilityFilter
  204. )
  205. };
  206. };
  207.  
  208. const mapDispatchToTodoListProps = (dispatch) => {
  209. return {
  210. onTodoClick: (id) => {
  211. dispatch({
  212. type: 'TOGGLE_TODO',
  213. id
  214. });
  215. }
  216. };
  217. };
  218.  
  219. const VisibleTodoList = connect(
  220. mapStateToTodoListProps,
  221. mapDispatchToTodoListProps
  222. )(TodoList);
  223.  
  224. const TodoApp = () => (
  225. <div>
  226. <AddTodo />
  227. <VisibleTodoList />
  228. <Footer />
  229. </div>
  230. );
  231.  
  232. const { Provider } = ReactRedux;
  233. const { createStore } = Redux;
  234.  
  235. ReactDOM.render(
  236. <Provider store={createStore(todoApp)}>
  237. <TodoApp />
  238. </Provider>,
  239. document.getElementById('root')
  240. );
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JS Bin</title>
  6. <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.0.4/redux.js"></script>
  7. <script src="https://fb.me/react-0.14.0.js"></script>
  8. <script src="https://fb.me/react-dom-0.14.0.js"></script>
  9. <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.0.0/react-redux.js"></script>
  10. </head>
  11. <body>
  12. <div id='root'></div>
  13. </body>
  14. </html>

[Redux] Generating Containers with connect() from React Redux (FooterLink)的更多相关文章

  1. [Redux] Generating Containers with connect() from React Redux (VisibleTodoList)

    Learn how to use the that comes with React Redux instead of the hand-rolled implementation from the ...

  2. [Redux] Generating Containers with connect() from React Redux (AddTodo)

    Code to be refacted: const AddTodo = (props, { store }) => { let input; return ( <div> < ...

  3. 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用

    先看效果图 github地址 github仓库 在线访问 初始化项目 #创建项目 create-react-app applist #如果没有安装create-react-app的话,先安装 npm ...

  4. React Redux Sever Rendering实战

    # React Redux Sever Rendering(Isomorphic JavaScript) ![React Redux Sever Rendering(Isomorphic)入门](ht ...

  5. react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware

    今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...

  6. react+redux教程(五)异步、单一state树结构、componentWillReceiveProps

    今天,我们要讲解的是异步.单一state树结构.componentWillReceiveProps这三个知识点. 例子 这个例子是官方的例子,主要是从Reddit中请求新闻列表来显示,可以切换reac ...

  7. react+redux教程(四)undo、devtools、router

    上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...

  8. react+redux+generation-modation脚手架添加一个todolist

    当我遇到问题: 要沉着冷静. 要管理好时间. 别被bug或error搞的不高兴,要高兴,又有煅炼思维的机会了. 要思考这是为什么? 要搞清楚问题的本质. 要探究问题,探究数据的流动. TodoList ...

  9. 实例讲解基于 React+Redux 的前端开发流程

    原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s ...

随机推荐

  1. 使用SqlCacheDependency依赖项让数据库变化后缓存失效

    SqlCacheDependency可以使缓存在数据库或者数据库某张表或者字段变化后让指定缓存失效.对于一些需要及时显示的信息比较有用. 需要.net2.0以后设sql server2005及以后版本 ...

  2. Javascript进阶篇——浏览器对象—Location、Navigator、userAgent、screen对象

    Location对象location用于获取或设置窗体的URL,并且可以用于解析URL.语法: location.[属性|方法] location对象属性图示: location 对象属性: loca ...

  3. 利用MetaWeblog API 自制博客发布小工具

    博客园提供了诸多数据接口, 利用这些接口可以很容易的实现博客的发布,修改,删除等 1.需要引用一个DLL:为CookComputing.XmlRpcV2 2.新建一个类,在其中是一些要实现的东西,如: ...

  4. 基础命名空间:反射 using System.Reflection

    反射概念:       .Net的应用程序由几个部分:‘程序集(Assembly)’.‘模块(Module)’.‘类型(class)’组成,程序集包含模块 模块包含类型,类型又包含 成员,而反射提供一 ...

  5. AFNetWorking 关于manager.requestSerializer.timeoutInterval 不起作用的问题

    之前一直遇到关于AFNetWorking请求时间设置了但是不起作用的情况,现用如下方式设置AF的超市时间即可. [manager.requestSerializer willChangeValueFo ...

  6. Gengxin讲STL系列——Set

    本系列第二篇blog 第一篇写的心潮澎湃,结果写完一看,这都是些什么玩意= =| Set的中文名称是“集合”.集合,高一数学必修一课本给出的定义已经很明确了,简单来讲就是一个不含重复元素的空间(个人定 ...

  7. C语言enum再学习

    通常来说我们使用enum是这样的: enum week{ Mon, Tue, ... Sun }; enum week w; w = Mon; 这里默认Mon~Sun的值为0~6 也可以自己定值 , ...

  8. poj1623 Squadtrees

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 需要求出按题目要求建四叉树所需的结点个数,和压缩后的四叉树的结点个数(压缩即只要将 ...

  9. vim 折叠技巧

    转自:http://www.2cto.com/os/201203/122133.html 主要命令: zf-创建折叠 zf20G--创建折叠,从当前行折叠到第20行 zfgg--创建折叠,从当前位置折 ...

  10. 用git提交代码步骤

    1.git add XXXX2.git commit - 'xxx'3.git stash4. //git pull --rebase 4. git rebase origin/develop git ...