react-redux

react 和 redux 的使用

在之前使用 react 时,我们把数据放到 state,通过 setState 可以触发 react 的更新渲染,而目前状态数据都交由 redux 管理。redux 数据状态发生改变时,相应的是我们通过 subscribe 方法绑定的 listener。所以我们需要绑定一个比较合适的监听函数作为状态变化时的相应,react 提供了主动触发 react 更新渲染的方法 forceUpdate

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'

const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'

const reducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
}

const store = createStore(reducer)

//展示组件
const Counter = ({ 
  count, onIncrement, onDecrement }) => (
  <div>
    <h1>{count}</h1>
    <button onClick={onIncrement}>+</button>
    <button onClick={onDecrement}>-</button>
  </div>
)

// 容器组件
class CounterContainer extends React.Component {
  componentDidMount() {
    this.unsubscribe = store.subscribe( () => {
      this.forceUpdate()
    })
  }
    
  componentWillUnmount() {
    this.unsubscribe()
  }
    
  render(){
    return <Counter 
      count={ store.getState() } 
      onIncrement = { () => store.dispatch({type: INCREMENT}) } 
      onDecrement = { () => store.dispatch({type: DECREMENT}) } 
    />
  }
}

ReactDOM.render(<CounterContainer />,document.getElementById('root'))

React是构建用户界面的框架,而 Redux 是为了解决状态管理问题专门开发的库,两者适合搭配但使用不是必须。React 官方专门提供了连接 react 和 redux 的库,react-redux。react-redux 主要提供两个方法

  • provider 是向整个应用传递store容器组件
  • connect 方法可以更具用户展示组件自动生成对应容器组件

provider 就像我们传递 store 用的容器组件,一般都会套在应用组件的最外层。而 connect 方法可以根据我们现有的展示组件,自动生成容器组件。connect 需要传递2个参数。

  1. mapStateToProps,用来对应state和props,并且传入参数时,在我们redux发生改变时,就会自动触发组件的更新。
  2. mapDispatchToProps,通过dispatch来传递对应的方法来触发action事件。

connect在获取了 redux 的 store 之后,再更具我们传入的方法把我们需要的部分对应到 props 属性当中,再传递到我们的组件里。

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider ,connect } from 'react-redux'
import PropTypes from 'prop-types'

const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'

const Reducer = (state = 0, action) => {
  switch (action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
}

const store = createStore(Reducer)

//展示组件
const Counter = ({ 
  count, onIncrement, onDecrement }) => (
  <div>
    <h1>{count}</h1>
    <button onClick={onIncrement}>+</button>
    <button onClick={onDecrement}>-</button>
  </div>
)

Counter.propTypes = {
  count: PropTypes.number.isRequired,
  onIncrement: PropTypes.func.isRequired,
  onDecrement: PropTypes.func.isRequired,
}

const mapStateToProps = (state) => (
  {
    count:state
  }
)

const mapDispatchToProps = (dispatch) => {
  return {
    onIncrement:()=>{
      dispatch({ type: INCREMENT })
    },
    onDecrement:() => {
      dispatch({type: DECREMENT})
    }
  }
}

// 容器组件
const CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter)

ReactDOM.render(
  <Provider store={store}>
    <CounterContainer />
  </Provider>
  ,document.getElementById('root'))

react-redux实现了很多优化,不会像 ReactDOM.render 和 foreUpdate 一样耗费效率,正式开发中建议使用 react-redux。