# 10.redux相关编码

# 1) index.js

import React from 'react'
import ReactDOM from 'react-dom'

import { Provider } from 'react-redux' ⭐⭐⭐
import store from './redux/store'  ⭐⭐⭐

import App from './containers/app'

ReactDOM.render((
  // 让所有组件的可以得到 state 数据  使用 Privider 组件包裹根组件
  <Provider store={store}>  ⭐⭐⭐
    <App />
  </Provider>
), document.getElementById('root'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2) container/app.js 容器组件

import React from 'react'
import { connect } from 'react-redux'

import { increment, decrement } from '../redux/action'
import Counter from '../components/counter'

// 这里包装为 <App count={count} increment={increment} decrement={decrement} >
export default connect(
  state => ({ count: state }),   // 当前只有一个reducer
  // state => ({ comments: state.comments, counter: state.counter }) 如果state有多个reducer 此时是一个对象 
  { increment, decrement }
)(Counter)
1
2
3
4
5
6
7
8
9
10
11
12
  • 需要下载依赖包
    npm install --save react-redux  //  专门用来简化react应用中使用redux
1

# 3)redux/actions.js

/**
 * 包含所有的 action 的构造函数
 * 同步的action都返回一个对象
 * 异步的action都返回一个函数
 */
import { INCREMENT, DECREMENT } from '../redux/action-types'

// 同步增加
export const increment = (number) => ({ type: INCREMENT, data: number })
// 同步减少 
export const decrement = (number) => ({ type: DECREMENT, data: number })

// 异步action
export const incrementAsync = (number) => {
  return dispatch => {
    // 在函数中执行异步代码
    setTimeout(() => {
      // 1s之后才去分发一个增加的action
      dispatch(increment(number))
    }, 1000)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 4) redux/action-types.js

/**
 * 包含所有action-type的常量字符串
 */

 export const INCREMENT = 'INCREMENT'
 export const DECREMENT = 'DECREMENT'
1
2
3
4
5
6

# 5) reducers.js

/**
 * 包含n个reducer的函数的模块
 */
import { INCREMENT, DECREMENT } from './action-types'

export function counter(state = 0, action) {
  console.log('counter', state, action);
  switch (action.type) {
    case INCREMENT:
      return state + action.data
    case DECREMENT:
      return state - action.data
    default:
      return state
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 6) store.js

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'

import { counter } from './reducers'

// 使用 浏览器插件
import { composeWithDevTools } from 'redux-devtools-extension'

// 生成一个 store 对象
const store = createStore(
  counter,  
  composeWithDevTools(applyMiddleware(thunk)) // 应用上异步中间件
  ) 

// 内部第一次调用reducer函数得到初始state
// console.log(store);

export default store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 需要安装插件和包

  • redux-devtools_2.15.2.crx (2.15.2版本以上, 否则报错: 找不到 state)

    npm install --save redux-thunk  // 异步中间件, 支持异步编程
1
    npm install --save redux-thunk  // 浏览器插件
1

# 7)components/counter.js UI组件

import React from 'react'
import PropTypes from 'prop-types'

export default class Counter extends React.Component {

  static propTypes = {
    count: PropTypes.number.isRequired,
    increment: PropTypes.func.isRequired,
    decrement: PropTypes.func.isRequired,
    incrementAsync: PropTypes.func.isRequired,
  }

  increment = () => {
    // 得到选择到的数量
    const number = this.select.value * 1
    // 调用store的方法更新状态
    this.props.increment(number)
  }
  decrement = () => {
    // 得到选择到的数量
    const number = this.select.value * 1
    // 调用store的方法更新状态
    this.props.decrement(number)
  }
  incrementIfOdd = () => {
    // 得到选择到的数量
    const number = this.select.value * 1
    // 将原来的数量和得到的数量进行累加
    const count = this.props.count
    if (count % 2 === 1) {
      // 调用store的方法更新状态
      this.props.increment(number)
    }
  }
  incrementAsync = () => {
    // 得到选择到的数量
    const number = this.select.value * 1
    this.props.incrementAsync(number)
  }
  render() {
    const { count } = this.props
    // debugger
    return (
      <div>
        <p>click {count} times</p>
        <div>
          <select ref={select => this.select = select}>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>&nbsp;
          <button onClick={this.increment}>+</button>&nbsp;
          <button onClick={this.decrement}>-</button>&nbsp;
          <button onClick={this.incrementIfOdd}>increment if odd</button>&nbsp;
          <button onClick={this.incrementAsync}>increment async</button>
        </div>
      </div>
    )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
上次更新: 2020/10/27 下午11:58:10