react-redux
主要: react-redux與redux并不完全一樣
- 主要特征
- ui組件
用戶提供的頁面
- 容器組件
由 React-Redux 自動生成
- 使用方法
- TodoList 是Ul組件
- mapStateToProps 將state映射到 UI 組件的參數(shù)(props)
- mapDispatchToProps 將用戶對 UI 組件的操作映射成 Action
- connect方法可以省略mapStateToProps參數(shù),那樣的話,UI 組件就不會訂閱Store,就是說 Store 的更新不會引起 UI 組件的更新。
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
- mapStateToProps
- 建立一個從(外部的)state對象到(UI 組件的)props對象的映射關系。
@params: state<Object> state對象
@params: props<Object> 容器組件的props對象
const mapStateToProps = (state, ownProps) => {
return {
active: state.count
}
}
- mapDispatchToProps
- 接收一個回調(diào)函數(shù)
擁有 dispatch, ownProps 兩個參數(shù)
const mapDispatchToProps = (
dispatch,
ownProps
) => {
return {
onClick: () => {
dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: ownProps.filter
});
}
};
}
- 接收一個對象
const mapDispatchToProps = {
onClick: (filter) => {
type: 'SET_VISIBILITY_FILTER',
filter: filter
};
}
- <Provider> 組件
- React-Redux 提供Provider組件,可以讓所有容器組件拿到state。
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
- store放在了上下文對象context上面。然后,子組件就可以從context拿到store
class VisibleTodoList extends Component {
componentDidMount() {
const { store } = this.context;
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
}
render() {
const props = this.props;
const { store } = this.context;
const state = store.getState();
// ...
}
}
VisibleTodoList.contextTypes = {
store: React.PropTypes.object
}
- 完整代碼
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider, connect } from 'react-redux'
// React component
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
}
// Action
const increaseAction = { type: 'increase' }
// Reducer
function counter(state = { count: 0 }, action) {
const count = state.count
switch (action.type) {
case 'increase':
return { count: count + 1 }
default:
return state
}
}
// Store
const store = createStore(counter)
// Map Redux state to component props
function mapStateToProps(state) {
return {
value: state.count
}
}
// Map Redux actions to component props
function mapDispatchToProps(dispatch) {
return {
onIncreaseClick: () => dispatch(increaseAction)
}
}
// Connected Component
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)