zoukankan      html  css  js  c++  java
  • [Redux] Redux: Extracting Container Components -- AddTodo

    Code to be refactored:

    const AddTodo = ({
      onAddClick
    }) => {
      let input;
    
      return (
        <div>
          <input ref={node => {
            input = node;
          }} />
          <button onClick={() => {
            onAddClick(input.value);
            input.value = '';
          }}>
            Add Todo
          </button>
        </div>
      );
    }

    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.

    const AddTodo = ({
      onAddClick
    }) => {
      let input;
    
      return (
        <div>
          <input ref={node => {
            input = node;
          }} />
          <button onClick={() => {
            store.dispatch({
              type: 'ADD_TODO',
              id: nextTodoId++,
              text: input.value
            });
            input.value = '';
          }}>
            Add Todo
          </button>
        </div>
      );
    };

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

    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={() => {
            store.dispatch({
              type: 'ADD_TODO',
              id: nextTodoId++,
              text: 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 />
        <VisibleTodoList />
        <Footer />
      </div>
    );
    
    const render = () => {
      ReactDOM.render(
        <TodoApp
          {...store.getState()}
        />,
        document.getElementById('root')
      );
    };
    
    store.subscribe(render);
    render();
  • 相关阅读:
    你了解幻读吗?
    http面试准备
    DNS域名解析过程,域名的认识
    ajax实现用户登陆,退出,java做后端
    serialize()与serializeArray()
    jquery中Json操作
    jquery字符串操作
    理解jQuery的$.extend与$.fn.extend
    HTML之间互相传参
    解决topjui中工具栏按钮删除刷新从属表
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5181802.html
Copyright © 2011-2022 走看看