forked from react-book/book-code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcounter-React,Redux and react-redux
More file actions
153 lines (135 loc) · 3.83 KB
/
counter-React,Redux and react-redux
File metadata and controls
153 lines (135 loc) · 3.83 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 文件路径 ./src/reducers/index.js
//属性不再只是一个值
const initialState = {
value:0,
star :0
}
const reducer = ( state =initialState, action) => {//这个地方的值是初始值
switch (action.type) {
case 'INCREMENT':
return Object.assign({},state,{ value : state.value+1})//对象中有多个属性所以必须这样写
case 'DECREMENT':
return Object.assign({},state,{ value : state.value-1})
case 'MULTIPLY':
return Object.assign({},state,{ value : state.value*2})
case 'STAR':
return Object.assign({},state,{ star : state.star+1})
default:
return state
}
}
export default reducer;
//文件路径 ./src/components/Counter.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
const ButtonAct = (props) => <button onClick={props.onClick}> {props.text} </button>
class Counter extends Component {
constructor(props) {
super(props);
this.incrementAsync = this.incrementAsync.bind(this);
this.incrementIfOdd = this.incrementIfOdd.bind(this);
this.incrementIfEven = this.incrementIfEven.bind(this);
}
incrementIfOdd() {
if (this.props.value % 2 !== 0) {
this.props.onIncrement()
}
}
incrementIfEven() {
if (this.props.value % 2 === 0) {
this.props.onIncrement()
}
}
incrementAsync() {
setTimeout(this.props.onIncrement, 1000)
}
render() {
const { value,star,onIncrement, onDecrement,onMultiply,onStar } = this.props
return (
<p>
Stars:{star}
<br/>
{' '}
<ButtonAct onClick={onStar} text="add star" />
{' '}
Clicked: {value} times
<br />
{' '}
<button onClick={onIncrement}>
+
</button>
{' '}
<ButtonAct onClick={onDecrement} text="-"/>
{' '}
<ButtonAct onClick={onMultiply} text="*" />
<br />
{' '}
<ButtonAct onClick={this.incrementIfOdd} text="Increment if odd"/>
<br/>
{' '}
<ButtonAct onClick={this.incrementAsync} text="Increment async"/>
<br/>
{' '}
<ButtonAct onClick={this.incrementIfEven} text="Increment if even" />
<br/>
</p>
)
}
}
Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncrement: PropTypes.func.isRequired,
onDecrement: PropTypes.func.isRequired
}
export default Counter
//文件路径 ./src/index.js
//store文件
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import Counter from './components/Counter'
import reducer from './reducers' //reducers文件夹下的index.js文件并未对reducer进行命名,所以我将其命名为reducer或counter无所谓
import {Provider,connect} from 'react-redux'
const store = createStore(reducer) //reducer函数
const rootEl = document.getElementById('root')
//value也作为counter组件的属性之一
const mapStateToProps = state => {
return {
value : state.value,
star : state.star
}
}
//将dispatch作为props传递给容器组件,可以是一个函数或者一个对象
//返回的这个对象的三个属性方法都将作为counter组件的属性之一
const mapDispatchToProps = state => {
return {
onIncrement : () => {
store.dispatch({
type:'INCREMENT'
});
},
onMultiply : () => {
store.dispatch({
type:'MULTIPLY'
});
},
onDecrement : () => {
store.dispatch({
type : 'DECREMENT'
});
},
onStar : () => {
store.dispatch({
type : 'STAR'
});
}
}
}
//将store中的有效信息派发给APP组件
//将自定义组件包装转换生成容器组件
const App = connect(mapStateToProps,mapDispatchToProps)(Counter) //App是一个容器组件
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,rootEl
)