蘑菇小姐会开花

react-redux

Presentation Component UI组件

don’t specify any behaviors and only are concerned with how things are rendered(how they look).
只负责UI的呈现,不带有任何业务逻辑。

Container Component 容器组件

specify behavior and pass data.
负责管理数据和业务逻辑,不负责UI的呈现。

Provider

将store通过context传递给子组件。

render 方法 返回props.children。

context makes the store avaliable to any component that it renders.
通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递props属性。

getChildContext 使用该方法将属性传递给子组件,并使用。可以覆盖,也可以增加。

childContextTypes provides child context (required in order for the child components to receive context).
声明需要传递给子组件的属性的数据类型。

contextTypes: specify the relevant context that we want to receive.
当需要在当前组件使用从上级组件传入的context的属性是,需要为用到的属性声明数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Provider extends Component {
getChildContext() {
return {
store: this.props.store // This corresponds to the `store` passed in as a prop
}
}
render() {
return this.props.children;
}
}

Provider.childContextTypes = {
store: PropTypes.object
}
// example
const App = () => (
<Provider store={store}>
<Comp />
</Provider>
)

connect

一个高阶函数?连接react组件和store,通过获取context的store,来和store中的数据进行链接。

首先接受四个参数mapStateToProps、mapDispatchToProps、mergeProps、options,返回传递给presentational Component的属性,
返回一个生产Component的函数(WrapWithComponent),
再接受一个被container Component render的presentational Component,
最后返回一个container Component。

特点:

  • 通过props.store获取祖先Component的store
  • props包括stateProps, dispatchProps, parentProps,合并在一起得到nextState,作为props传递给真正的Component
  • componentDidMount时,添加事件this.store.subscribe(this.handleChange),实现页面交互
  • shouldComponentUpdate时判断是否有避免进行渲染,提升页面性能,并得到nextState
  • componentWillUnmount时移除注册的事件this.handleChange
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
<!--connect 写法-->
const mapStateTopProps = state => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}

const toggleTodo = id => {
return {
type: 'TOGGLE_TODO',
id
}
}

const mapDispatchToProps = dispatch => {
return {
onTodoClick: id => {
dispatch(toggleTodo(id))
}
}
}

const VisibleTodoList = connect(mapStateTopProps, mapDispatchToProps)(TodoList)

<!--context 写法-->
class VisibleTodoList extends Component {
componentDidMount() {
const { store } = this.context;
this.unsubscribe = store.subscribe(() => {
this.forceUpdate()
})
}
componentWillUnmount() {
this.unsubscribe()
}
render() {
const { store } = this.context
const state = store.getState()
return <TodoList
todos={getVisibleTodos(state.todos, state.visibilityFilter)}
onTodoClick={id => {
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}}
/>
}
}

VisibleTodoList.contextTypes = {
store: PropTypes.object
}

mapStateToProps

takes the Redux store’s state, and returns the props that we need to pass to the presentational component so it can be rendered with the current state.

mapStateToProps(state, ownProps): stateProps
接受的第一个参数是state,第二个参数是容器组件本身的props,返回一个对象(每个键名对应UI组件的同名参数)。

订阅store,将store中的数据作为props绑定到UI组件上,当state更新后,自动执行,重新计算UI组件的参数,触发UI组件的重绘。

1
2
3
4
5
const mapStateTopProps = state => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}

mapDispatchToProps

accepts the dispatch() from store as its only argument, and returns the props that use the dispatch method to dispatch actions. So it returns the callback props that should be passed to the presentational component.

mapDispatchToProps(dispatch, ownProps): dispatchProps
接受的第一个参数是dispatch,第二个参数是容器组件本身的props,返回一个对象(每个键名对应UI组件的同名参数)。

将action作为props绑定到UI组件上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// action
const toggleTodo = id => {
return {
type: 'TOGGLE_TODO',
id
}
}

const mapDispatchToProps = dispatch => {
return {
onTodoClick: id => {
dispatch(toggleTodo(id))
}
}
}

mergeProps

merge stateProps&dispatchProps&ownProps.
[mergeProps(stateProps, dispatchProps, ownProps): props]
类似于Object.assign。

Tip

Every time a function does too many things, it’s best to break them up into other functions that each address only one concern.

坚持原创技术分享,您的支持将鼓励我继续创作!