Code to be refactored:

  1. const AddTodo = ({
  2. onAddClick
  3. }) => {
  4. let input;
  5.  
  6. return (
  7. <div>
  8. <input ref={node => {
  9. input = node;
  10. }} />
  11. <button onClick={() => {
  12. onAddClick(input.value);
  13. input.value = '';
  14. }}>
  15. Add Todo
  16. </button>
  17. </div>
  18. );
  19. }

Finally, in the previous lesson, I made app ToDo a presentational component, but I'm going to backtrack on this now. I will copy-paste the dispatch call back in line into the onClick handler inside the component because there isn't really a lot of presentation or behavior here.

It's easier to keep them together until we figure out how to split the presentation. For example, if in the future, we're going to have something like a form component, we may split it, but for now we'll keep them together.

  1. const AddTodo = ({
  2. onAddClick
  3. }) => {
  4. let input;
  5.  
  6. return (
  7. <div>
  8. <input ref={node => {
  9. input = node;
  10. }} />
  11. <button onClick={() => {
  12. store.dispatch({
  13. type: 'ADD_TODO',
  14. id: nextTodoId++,
  15. text: input.value
  16. });
  17. input.value = '';
  18. }}>
  19. Add Todo
  20. </button>
  21. </div>
  22. );
  23. };

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

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 { createStore } = Redux;
  58. const store = createStore(todoApp);
  59.  
  60. const { Component } = React;
  61.  
  62. const Link = ({
  63. active,
  64. children,
  65. onClick
  66. }) => {
  67. if (active) {
  68. return <span>{children}</span>;
  69. }
  70.  
  71. return (
  72. <a href='#'
  73. onClick={e => {
  74. e.preventDefault();
  75. onClick();
  76. }}
  77. >
  78. {children}
  79. </a>
  80. );
  81. };
  82.  
  83. class FilterLink extends Component {
  84. componentDidMount() {
  85. this.unsubscribe = store.subscribe(() =>
  86. this.forceUpdate()
  87. );
  88. }
  89.  
  90. componentWillUnmount() {
  91. this.unsubscribe();
  92. }
  93.  
  94. render() {
  95. const props = this.props;
  96. const state = store.getState();
  97.  
  98. return (
  99. <Link
  100. active={
  101. props.filter ===
  102. state.visibilityFilter
  103. }
  104. onClick={() =>
  105. store.dispatch({
  106. type: 'SET_VISIBILITY_FILTER',
  107. filter: props.filter
  108. })
  109. }
  110. >
  111. {props.children}
  112. </Link>
  113. );
  114. }
  115. }
  116.  
  117. const Footer = () => (
  118. <p>
  119. Show:
  120. {' '}
  121. <FilterLink
  122. filter='SHOW_ALL'
  123. >
  124. All
  125. </FilterLink>
  126. {', '}
  127. <FilterLink
  128. filter='SHOW_ACTIVE'
  129. >
  130. Active
  131. </FilterLink>
  132. {', '}
  133. <FilterLink
  134. filter='SHOW_COMPLETED'
  135. >
  136. Completed
  137. </FilterLink>
  138. </p>
  139. );
  140.  
  141. const Todo = ({
  142. onClick,
  143. completed,
  144. text
  145. }) => (
  146. <li
  147. onClick={onClick}
  148. style={{
  149. textDecoration:
  150. completed ?
  151. 'line-through' :
  152. 'none'
  153. }}
  154. >
  155. {text}
  156. </li>
  157. );
  158.  
  159. const TodoList = ({
  160. todos,
  161. onTodoClick
  162. }) => (
  163. <ul>
  164. {todos.map(todo =>
  165. <Todo
  166. key={todo.id}
  167. {...todo}
  168. onClick={() => onTodoClick(todo.id)}
  169. />
  170. )}
  171. </ul>
  172. );
  173.  
  174. const AddTodo = ({
  175. onAddClick
  176. }) => {
  177. let input;
  178.  
  179. return (
  180. <div>
  181. <input ref={node => {
  182. input = node;
  183. }} />
  184. <button onClick={() => {
  185. store.dispatch({
  186. type: 'ADD_TODO',
  187. id: nextTodoId++,
  188. text: input.value
  189. });
  190. input.value = '';
  191. }}>
  192. Add Todo
  193. </button>
  194. </div>
  195. );
  196. };
  197.  
  198. const getVisibleTodos = (
  199. todos,
  200. filter
  201. ) => {
  202. switch (filter) {
  203. case 'SHOW_ALL':
  204. return todos;
  205. case 'SHOW_COMPLETED':
  206. return todos.filter(
  207. t => t.completed
  208. );
  209. case 'SHOW_ACTIVE':
  210. return todos.filter(
  211. t => !t.completed
  212. );
  213. }
  214. }
  215.  
  216. class VisibleTodoList extends Component {
  217.  
  218. componentDidMount() {
  219. this.unsubscribe = store.subscribe(() =>
  220. this.forceUpdate()
  221. );
  222. }
  223.  
  224. componentWillUnmount() {
  225. this.unsubscribe();
  226. }
  227.  
  228. render() {
  229.  
  230. const props = this.props;
  231. const state = store.getState();
  232.  
  233. return (
  234. <TodoList
  235. todos={
  236. getVisibleTodos(
  237. state.todos,
  238. state.visibilityFilter
  239. )
  240. }
  241. onTodoClick={id =>
  242. store.dispatch({
  243. type: 'TOGGLE_TODO',
  244. id
  245. })
  246. }
  247. />
  248. );
  249. }
  250. }
  251.  
  252. let nextTodoId = 0;
  253. const TodoApp = ({
  254. todos,
  255. visibilityFilter
  256. }) => (
  257. <div>
  258. <AddTodo />
  259. <VisibleTodoList />
  260. <Footer />
  261. </div>
  262. );
  263.  
  264. const render = () => {
  265. ReactDOM.render(
  266. <TodoApp
  267. {...store.getState()}
  268. />,
  269. document.getElementById('root')
  270. );
  271. };
  272.  
  273. store.subscribe(render);
  274. render();

[Redux] Redux: Extracting Container Components -- AddTodo的更多相关文章

  1. [Redux] Extracting Container Components (FilterLink)

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

  2. [Redux] Extracting Container Components -- Complete

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

  3. [Redux] Extracting Container Components -- VisibleTodoList

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

  4. [Redux] Extracting Presentational Components -- AddTodo

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

  5. [React] 11 - Redux: redux

    Ref: Redux中文文档 Ref: React 讀書會 - B團 - Level 19 Redux 深入淺出 Ref: React+Redux 分享會 Ruan Yifeng, Redux 架构: ...

  6. Presentational and Container Components

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

  7. Flux --> Redux --> Redux React 入门

    本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...

  8. [Redux] redux的概述

    redux 的概述 随着 javascript 单页应用的不断发展,javascript 需要管理比以往都要多的状态,管理不断变化的 state 非常困难,数据流动不断变的模糊不可预测,代码的开发与维 ...

  9. Flux --> Redux --> Redux React 基础实例教程

    本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...

随机推荐

  1. Nested Class Templates

      Templates can be defined within classes or class templates, in which case they are referred to as ...

  2. UDP C/S编程

    UDP C/S编程的步骤如下图所示与TCP C/S通信的区别在于:服务端没有设置监听和等待连接的过程.客户端没有连接服务端的过程.基于UDP的通信时不可靠地,面向无连接的,发送的数据无法确切知道对方收 ...

  3. 如何解决svn图标不显示呢?

    svn图标不显示解决 确保设置正确: 右键->TortoiseSVN->setting->Icon Overlays->Status cache->default/She ...

  4. ContextLoaderListener初始化的前后文和DispatcherServlet初始化的上下文关系

    ContextLoaderListener初始化的上下文加载的Bean是对于整个应用程序共享的,不管是使用什么表现层技术,一般如DAO层.Service层Bean: DispatcherServlet ...

  5. 模块计算机类型“X64”与目标计算机类型“x86”冲突

    问题描述:在X64 平台上开发dll 文件,在生成dll时Vs 2010 出现如下错误 :"fatal error LNK1112: 模块计算机类型"X64"与目标计算机 ...

  6. Protobuf实现Android Socket通讯开发教程

    本节为您介绍Protobuf实现Android Socket通讯开发教程,因此,我们需要先了理一下protobuf 是什么? Protocol buffers是一种编码方法构造的一种有效而可扩展的格式 ...

  7. 开发日志_Jan.9

    今天主要工作为修改昨天的碰撞引擎不符合预期的部分. 经过了昨天的工作,碰撞算法已经初见雏形.但是主要有两个问题: 碰撞反弹的方向与预期不符合 碰撞后球与机器人存在一个"黏在一起"的 ...

  8. 1:scrapy框架原理与环境搭设

    1:原理图: (*此图来自网络) 2:开发过程: 1)编写items.py,确定要抓取的关键字段名称 2)编写spider,确定发送request的形式以及对于response的处理 3)编写pipe ...

  9. Image控件的简单使用示例1

    Image控件加载图片包括加载动态图片,加载静态图片两种方式.一.加载动态图片通过生成一个BitmapImage,创建该对象后,赋给Image的Source即可.加载的形式: 示例1 BitmapIm ...

  10. 如何获取外网Ip呢, 终于找到方法了

    临时更换网址:http://20140507.ip138.com/ic.asp 这个网址能同时获取ip和城市名字 上面的网址如何来的呢,其实很简单,随便打开一个获取Ip的网站,比如http://www ...