viviier

React-redux 入门实例(ruanyifeng)

React-redux

React-redux将组件分为两大类:UI组件和容器组件。

UI组件特点:

  • 只负责UI的呈现,不带有任何的业务逻辑
  • 没有状态(即不使用this.state属性)
  • 所有数据都由参数(this.props)提供
  • 不使用任何的Redux的API

计数器例子的Counter组件就是一个UI组件,他所需要的数据在render里由props提供

容器组件特点:

  • 负责管理数据和业务逻辑,不负责UI的呈现
  • 带有内部状态
  • 使用Redux的API

换句话说,UI组件负责UI的呈现,容器组件负责管理数据和逻辑。
React-redux规定,所有的UI组件都由用户提供,容器组件则有React-redux自动生成。也就是说用户负责视觉层,状态管理全交给它。

计数器

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
/* reducer */
const reducer = (state=0, action) => {
switch(action.type) {
case 'ADD':
return state+1;
case 'DEC':
return state-1;
default:
return state;
}
};
/* 创建状态 */
const { createStore } = Redux;
const store = createStore(reducer);
let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action);
next(action);
console.log('next state', store.getState());
}
/* 然后构建Counter组件 */
const { Component } = React;
class Counter extends Component {
render(){
const {value, increment, deccrement} = this.props;
return (
<div>
<h1>{value}</h1>
<button onClick={increment}>+</button>
<button onClick={deccrement}>-</button>
</div>
)
}
}
/* 首先写好需要实时渲染的虚拟dom */
const render = () => {
ReactDOM.render(
<Counter
value={store.getState()}
increment={() => {
store.dispatch({
type: 'ADD'
})
}}
deccrement={() => {
store.dispatch({
type: 'DEC'
})
}}
/>,
document.getElementById('root')
)
};
/* 然后初始化执行render,并且监听render */
render();
store.subscribe(render);

使用connect和Provider来生成计数器

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
const { Component, PropTypes } = React
const { createStore } = Redux
const { Provider, connect } = ReactRedux
/* UI层面 */
class Counter extends Component {
render() {
const { value, onIncreaseClick } = this.props
return (
<div>
<span>{value}</span>
<button onClick={onIncreaseClick}>Increase</button>
</div>
)
}
}
Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncreaseClick: PropTypes.func.isRequired
}
/* value映射state,onIncreaseClick映射dispatch */
function mapStateToProps(state) {
return {
value: state.count
}
}
function mapDispatchToProps(dispatch) {
return {
onIncreaseClick: () => dispatch(increaseAction)
}
}
// action
const increaseAction = { type: 'increase' }
/* 生成容器组件 */
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter)
/* reducer */
function counter(state = {count: 0}, action) {
const count = state.count;
switch(action.type) {
case 'increase':
return { count: count+1 }
default:
return state
}
}
const store = createStore(counter)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)

mapStateToProps会订阅store,每当state更新时,就会重新计算UI组件的参数,从而触发UI组件的重新渲染。

------本文结束感谢阅读------