zoukankan      html  css  js  c++  java
  • [Redux] Passing the Store Down with <Provider> from React Redux

    Previously, we wrote the Provider component by ourself:

    class Provider extends Component {
      getChildContext() {
        return {
          store: this.props.store
        }; 
      }
    
      render() {
        return this.props.children;
      }
    }
    Provider.childContextTypes = {
      store: React.PropTypes.object
    };

    Then we can get 'store' from the 'context' from each child container component:

    class VisibleTodoList 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 (
          <TodoList
            todos={
              getVisibleTodos(
                state.todos,
                state.visibilityFilter
              )
            }
            onTodoClick={id =>
              store.dispatch({
                type: 'TOGGLE_TODO',
                id
              })            
            }
          />
        );
      }
    }
    VisibleTodoList.contextTypes = {
      store: React.PropTypes.object
    };

    or Persentiaonal component:

    const AddTodo = (props, { store }) => {
      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>
      );
    };
    AddTodo.contextTypes = {
      store: React.PropTypes.object
    };

    Because the solution is so convenient, we can use library instead of writing our own Provider:

    So we can remvoe all the whole Provider class component, instead of we do:

    const {Provider} = ReactRedux;

    In html:

     <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.0.0/react-redux.js"></script>

    ---------

    Code:

    <!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>
    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,
      children,
      onClick
    }) => {
      if (active) {
        return <span>{children}</span>;
      }
    
      return (
        <a href='#'
           onClick={e => {
             e.preventDefault();
             onClick();
           }}
        >
          {children}
        </a>
      );
    };
    
    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
    };
    
    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;
    const AddTodo = (props, { store }) => {
      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>
      );
    };
    AddTodo.contextTypes = {
      store: React.PropTypes.object
    };
    
    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() {
        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 (
          <TodoList
            todos={
              getVisibleTodos(
                state.todos,
                state.visibilityFilter
              )
            }
            onTodoClick={id =>
              store.dispatch({
                type: 'TOGGLE_TODO',
                id
              })            
            }
          />
        );
      }
    }
    VisibleTodoList.contextTypes = {
      store: React.PropTypes.object
    };
    
    const TodoApp = () => (
      <div>
        <AddTodo />
        <VisibleTodoList />
        <Footer />
      </div>
    );
    
    const {Provider} = ReactRedux;
    
    const { createStore } = Redux;
    
    ReactDOM.render(
      <Provider store={createStore(todoApp)}>
        <TodoApp />
      </Provider>,
      document.getElementById('root')
    );
  • 相关阅读:
    poj 3528 (三维几何求凸包+凸包表面积)
    dijkstra模板(好像是斐波那契额堆优化,但我为什么看起来像优先队列优化,和spfa一样)
    最大空凸包模板
    ICPC 2017–2018, NEERC, Northern Subregional Contest St Petersburg, November 4, 2017 I题
    hdu 5248 序列变换
    hdu 2063(二分图模板测试)
    组合数
    85. Maximal Rectangle 由1拼出的最大矩形
    750. Number Of Corner Rectangles四周是点的矩形个数
    801. Minimum Swaps To Make Sequences Increasing 为使两个数组严格递增,所需要的最小交换次数
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5184879.html
Copyright © 2011-2022 走看看