# 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
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
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
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
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
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
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>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>increment if odd</button>
<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
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