[Redux] Generating Containers with connect() from React Redux (FooterLink)

來源:互聯網
上載者:User

標籤:

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>

 

[Redux] Generating Containers with connect() from React Redux (FooterLink)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.