Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React-Redux #12

Open
WangShuXian6 opened this issue May 2, 2018 · 2 comments
Open

React-Redux #12

WangShuXian6 opened this issue May 2, 2018 · 2 comments

Comments

@WangShuXian6
Copy link
Owner

WangShuXian6 commented May 2, 2018

connect方法接受两个参数:mapStateToProps和mapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

import { connect } from 'react-redux'

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

mapStateToProps是一个函数。它的作用就是像它的名字那样,建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系
mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

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

// 容器组件的代码
//    <FilterLink filter="SHOW_ALL">
//      All
//    </FilterLink>

const mapStateToProps = (state, ownProps) => {
  return {
    active: ownProps.filter === state.visibilityFilter
  }
}
@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented May 2, 2018

计数器示例-版本1
index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
//import App from './App';
import registerServiceWorker from './registerServiceWorker';
import {store} from './store'
import {Provider} from 'react-redux'
import Counter2 from './components/counter2'

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

store.js

import {createStore} from 'redux'
import counter2 from './reducers/counter2'

const store = createStore(counter2)
export {store}

components/counter2.js

import React, {Component} from 'react'
import {increaseAction} from "../actions/increase";
import PropTypes from 'prop-types'
import {connect} from 'react-redux'

class Counter2 extends Component {
  render() {
    const {value, onIncreaseClick} = this.props
    return (
        <div class="counter2">
          <span>{value}</span>
          <button onClick={onIncreaseClick}>Increase</button>
        </div>
    )
  }
}

Counter2.propTypes = {
  value: PropTypes.number.isRequired,
  onIncreaseClick: PropTypes.func.isRequired
}

function mapStateToProps(state) {
  return {
    value: state.count
  }
}

function mapDispatchToProps(disptch) {
  return {
    onIncreaseClick: () => {
      disptch(increaseAction())
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Counter2)

actions/increase.js

export function increase() {
  return {
    type: 'increase'
  }
}

reducers/counter2.js

export default (state = {count: 0}, action) => {
  const count = state.count
  switch (action.type) {
    case 'increase':
      return {count: count + 1}
    default:
      return state
  }
}

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented May 2, 2018

计数器示例-版本2
index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
//import App from './App';
import registerServiceWorker from './registerServiceWorker';
import {store} from './store'
import {Provider} from 'react-redux'
import Counter2 from './components/counter2'

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

store.js

import {createStore} from 'redux'
import counter2 from './reducers/counter2'

const store = createStore(counter2)
export {store}

components/counter2.js

import React, {Component} from 'react'
import * as actions from "../actions/increase";
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

class Counter2 extends Component {
  handleClick() {
    this.props.increase()
  }

  render() {
    const {value} = this.props
    return (
        <div class="counter2">
          <span>{value}</span>
          <button onClick={this.handleClick.bind(this)}>Increase</button>
        </div>
    )
  }
}

Counter2.propTypes = {
  value: PropTypes.number.isRequired,
  onIncreaseClick: PropTypes.func.isRequired
}

function mapStateToProps(state) {
  return {
    value: state.count
  }
}

let mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch)

export default connect(mapStateToProps, mapDispatchToProps)(Counter2)

actions/increase.js

export function increase() {
  return {
    type: 'increase'
  }
}

reducers/counter2.js

export default (state = {count: 0}, action) => {
  const count = state.count
  switch (action.type) {
    case 'increase':
      return {count: count + 1}
    default:
      return state
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant