美文网首页
React实战之Redux

React实战之Redux

作者: 码农随想录 | 来源:发表于2017-09-02 20:57 被阅读277次

    Redux、React-Redux 简介


    Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
    尽管 Redux 来自 React 社区,但它并不依赖于 React。无论有没有 JavaScript 框架,比如 React、Angular、Backbone 或 Cycle.js,都可以使用 Redux。

    React-Redux 是Redux 方提供的 React 绑定。
    提供了一个组件和一个API帮助Redux 和 React 进行绑定,一个是 React 组件<Provider/> ,一个是 connect()。
    <Provider/> 接受一个 store 作为props,它是 个 Redux 应用的顶层组件,而 connect() 提供了在 个 React 应用的任意组件中获取 store 中数据的功能。

    Redux基础

    一、Store

    Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。

    Redux 提供createStore这个函数,用来生成 Store。

    //react-app/index.js
    
    import React from 'react'
    import { render } from 'react-dom'
    import { createStore } from 'redux'
    import { Provider } from 'react-redux'
    import App from './components/App'
    import reducer from './reducers'
    
    //用redux创建的store
    //createStore函数接受另一个函数作为参数,返回新生成的 Store 对象。
    const store = createStore(reducer)
    // Provider就是把我们用redux创建的store传递到内部的其他组件。
    //让内部组件可以享有这个store并提供对state的更新。
    render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    )
    

    二、State

    Store对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State。

    三、Action

    Action 就是 View 发出的通知,表示 State 应该要发生变化了。

    Action 是一个对象。其中的type
    属性是必须的,表示 Action 的名称。其他属性可以自由设置,社区有一个规范可以参考。

    //react-app/actions/index.js
    
    export const setVisibilityFilter = (filter) => ({
      type: 'SET_VISIBILITY_FILTER',
      filter
    })
    

    四、Reducer

    Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。

    Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

    Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。

    //react-app/reducers/index.js
    
    import { combineReducers } from 'redux'
    import visibilityFilter from './visibilityFilter'
    
    const todoApp = combineReducers({
      visibilityFilter
    })
    
    export default todoApp
    
    //react-app/reducers/visibilityFilter.js
    
    const visibilityFilter = (state = 'SHOW_ALL', action) => {
      switch (action.type) {
        case 'SET_VISIBILITY_FILTER':
          return action.filter
        default:
          return state
      }
    }
    
    export default visibilityFilter
    

    React-Redux基础

    一、组件

    React-Redux 将所有组件分成两大类:
    1、展示型组件(presentational component)
    2、容器型组件(container component)

    展示型组件负责 UI 的呈现,容器型件负责管理数据和逻辑。

    此外React-Redux 提供Provider组件,负责让容器组件拿到state

    1、Provider组件

    //react-app/index.js
    
    import React from 'react'
    import { render } from 'react-dom'
    import { createStore } from 'redux'
    import { Provider } from 'react-redux'
    import App from './components/App'
    import reducer from './reducers'
    
    //用redux创建的store
    //createStore函数接受另一个函数作为参数,返回新生成的 Store 对象。
    const store = createStore(reducer)
    // Provider就是把我们用redux创建的store传递到内部的其他组件。
    //让内部组件可以享有这个store并提供对state的更新。
    render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    )
    

    2、展示型组件特点

    1、只负责 UI 的呈现,不带有任何业务逻辑
    2、没有状态(即不使用this.state这个变量)
    3、所有数据都由参数(this.props)提供
    4、不使用任何 Redux 的 API

    //react-app/components/App.js
    
    import React from 'react'
    import Footer from './Footer'
    
    const App = () => (
      <div>
        <Footer />
      </div>
    )
    
    export default App
    
    //react-app/components/Footer.js
    
    import React from 'react'
    import FilterLink from '../containers/FilterLink'
    
    const Footer = () => (
      <p>
        Show:
        {" "}
        <FilterLink filter="SHOW_ALL">
          All
        </FilterLink>
        {", "}
        <FilterLink filter="SHOW_ACTIVE">
          Active
        </FilterLink>
        {", "}
        <FilterLink filter="SHOW_COMPLETED">
          Completed
        </FilterLink>
      </p>
    )
    
    export default Footer
    
    //react-app/components/Link.js
    
    import React from 'react'
    import PropTypes from 'prop-types'
    
    const Link = ({ active, children, onClick }) => {
      if (active) {
        return <span>{children}</span>
      }
    
      return (
        // eslint-disable-next-line
        <a href="#"
           onClick={e => {
             e.preventDefault()
             onClick()
           }}
        >
          {children}
        </a>
      )
    }
    
    Link.propTypes = {
      active: PropTypes.bool.isRequired,
      children: PropTypes.node.isRequired,
      onClick: PropTypes.func.isRequired
    }
    
    export default Link
    
    

    3、容器型组件特点

    1、负责管理数据和业务逻辑,不负责 UI 的呈现
    2、带有内部状态
    3、使用 Redux 的 API

    //react-app/containers/FilterLink.js
    
    import { connect } from 'react-redux'
    import { setVisibilityFilter } from '../actions'
    import Link from '../components/Link'
    
    const mapStateToProps = function(state, ownProps) {
        console.log('state : ', state);
        console.log('ownProps : ', ownProps);
        return {
      active: ownProps.filter === state.visibilityFilter
    }
    }
    
    
    const mapDispatchToProps = function(dispatch, ownProps){
        console.log('mapDispatchToProps')
         return {
          onClick: () => {
            dispatch(setVisibilityFilter(ownProps.filter))
          }
        }
    }
    
    const FilterLink = connect(
      mapStateToProps,
      mapDispatchToProps
    )(Link)
    
    export default FilterLink
    

    4、展示型组件和容器型组件对比

    展示型组件和容器型组件对比

    二、connect()

    React-Redux 提供connect方法,用于从 UI 组件生成容器组件。

    connect([mapStateToProps], [mapDipatchToProps], [mergeProps], [options])
    

    connect()一共有四个参数,但我这里只说基本的两个,mapStateToProps和mapDispatchToProps。

    1、mapStateToProps

    mapStateToProps是一个函数,建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。

    mapStateToProps执行后应该返回一个对象,里面的每一个键值对就是一个映射。

    mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。

    mapStateToProps的第一个参数总是state对象,还可以使用第二个参数,代表容器组件的props对象。

    使用ownProps作为参数后,如果容器组件的参数发生变化,也会引发 UI 组件重新渲染。

    const mapStateToProps = function(state, ownProps) {
        return {
            active: ownProps.filter === state.visibilityFilter
        }
    }
    

    2、mapDispatchToProps

    store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。

    2.1、mapDispatchToProps是一个函数

    如果mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数。

    mapDispatchToProps作为函数,应该返回一个对象,该对象的每个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action。

    const mapDispatchToProps = function(dispatch, ownProps) {
        return {
            onClick: () => {
                dispatch(setVisibilityFilter(ownProps.filter))
            }
        }
    }
    
    2.2、mapDispatchToProps是一个对象

    它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出。举例来说,上面的mapDispatchToProps写成对象就是下面这样。

    const mapDispatchToProps = {
      onClick: (filter) => {
        setVisibilityFilter(filter)
      };
    }
    

    Redux 的核心 作流程

    Redux 的核心 作流程

    最后

    如果有疑问,请下载示例代码,也可以欢迎私信或者留言给我。
    如果觉得对你有帮助,请点个👍,谢谢

    相关文章

      网友评论

          本文标题:React实战之Redux

          本文链接:https://www.haomeiwen.com/subject/mclgdxtx.html