zoukankan      html  css  js  c++  java
  • [Redux] Generating Containers with connect() from React Redux (FooterLink)

    Code to be refactored:

    class FilterLink extends Component {
      componentDidMount() {
        const { store } = this.context;
        this.unsubscribe = store.subscribe(() =>
          this.forceUpdate()
        );
      }
      
      componentWillUnmount() {
        this.unsubscribe();
      }
      
      render() {
        const props = this.props;
        const { store } = this.context;
        const state = store.getState();
        
        return (
          <Link
            active={
              props.filter ===
              state.visibilityFilter
            }
            onClick={() =>
              store.dispatch({
                type: 'SET_VISIBILITY_FILTER',
                filter: props.filter
              })
            }
          >
            {props.children}
          </Link>
        );
      }
    }
    FilterLink.contextTypes = {
      store: React.PropTypes.object
    };

    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:

    const mapStateToLinkProps = (
      state,
      ownProps
    ) => {
      return {
        active: ownProps.filter === state.visibilityFilter
      }
    }

    Second, we need to write mapDispatchToProp function:

    const mapDispatchToLinkProps = (
      dispatch,
      ownProps
    ) => {
      return {
        onClick: () => {
          dispatch({
                type: 'SET_VISIBILITY_FILTER',
                filter: ownProps.filter
              })
        }
      }
    }

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

    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:

    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 { Component } = React;
    
    const Link = ({
      active,
      onClick,
      children,
    }) => {
      if (active) {
        return <span>{children}</span>;
      }
    
      return (
        <a href='#'
           onClick={e => {
             e.preventDefault();
             onClick();
           }}
        >
          {children}
        </a>
      );
    };
    
    const { connect } = ReactRedux;
    const mapStateToLinkProps = (
      state,
      ownProps
    ) => {
      return {
        active: ownProps.filter === state.visibilityFilter
      }
    }
    
    const mapDispatchToLinkProps = (
      dispatch,
      ownProps
    ) => {
      return {
        onClick: () => {
          dispatch({
                type: 'SET_VISIBILITY_FILTER',
                filter: ownProps.filter
              })
        }
      }
    }
    
    const FilterLink = connect(mapStateToLinkProps, mapDispatchToLinkProps)(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>
    );
    
    
    
    let nextTodoId = 0;
    let AddTodo = ({ dispatch }) => {
      let input;
    
      return (
        <div>
          <input ref={node => {
            input = node;
          }} />
          <button onClick={() => {
            dispatch({
              type: 'ADD_TODO',
              id: nextTodoId++,
              text: input.value
            })
            input.value = '';
          }}>
            Add Todo
          </button>
        </div>
      );
    };
    AddTodo = connect()(AddTodo);
    
    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
          );
      }
    }
    
    const mapStateToTodoListProps = (state) => {
      return {
        todos: getVisibleTodos(
          state.todos,
          state.visibilityFilter
        )
      };
    };
    
    const mapDispatchToTodoListProps = (dispatch) => {
      return {
        onTodoClick: (id) => {
          dispatch({
            type: 'TOGGLE_TODO',
            id
          });
        }
      };
    };
    
    
    const VisibleTodoList = connect(
      mapStateToTodoListProps,
      mapDispatchToTodoListProps
    )(TodoList);
    
    const TodoApp = () => (
      <div>
        <AddTodo />
        <VisibleTodoList />
        <Footer />
      </div>
    );
    
    const { Provider } = ReactRedux;
    const { createStore } = Redux;
    
    ReactDOM.render(
      <Provider store={createStore(todoApp)}>
        <TodoApp />
      </Provider>,
      document.getElementById('root')
    );
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS Bin</title>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.0.4/redux.js"></script>
       <script src="https://fb.me/react-0.14.0.js"></script>
      <script src="https://fb.me/react-dom-0.14.0.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.0.0/react-redux.js"></script>
    </head>
    <body>
      <div id='root'></div>
    </body>
    </html>
  • 相关阅读:
    zabbix_QQ邮件告警部署(待续。。。。。。)
    FTP服务的搭建
    项目: NFS服务的搭建
    用ngxin搭建简单的下载站点
    脚本设定开机自启动
    自建小项目:自动化脚本安装ngnix项目
    Zabbix Web操作深入(待续------)
    DHCP原理与配置
    PXE高效能网络批量装机
    DNS域名解析服务
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5186821.html
Copyright © 2011-2022 走看看