借助于context
的跨级通信能力,可以将store
管理数据的模式应用于每个组件当中。即将store
通过context
传递到子组件,一方面子组件可以通过store.dispatch()
触发store
中数据更新,另一方面子组件可以通过store.getState()
方法获取最终的更新状态,刷新UI。
Redux解读
React之Context
1.目录结构
制作一个更换主题色的App
参考【结合 context 和 store】
store.js
function createStore (reducer) {
let state = null
const listeners = []
const subscribe = (listener) => listeners.push(listener)
const getState = () => state
const dispatch = (action) => {
state = reducer(state, action)
listeners.forEach((listener) => listener())
}
dispatch({}) // 初始化 state
return { getState, dispatch, subscribe }
}
const themeReducer = (state, action) => {
if (!state) return {
themeColor: 'red'
}
switch (action.type) {
case 'CHANGE_COLOR':
return { ...state, themeColor: action.themeColor }
default:
return state
}
}
export default createStore(themeReducer)
Index.js
引入store
,通过context
将store传递给子组件。
import React, { Component } from 'react'
import Header from './Header'
import Content from './Content'
import PropTypes from 'prop-types';
import store from '../react-redux/store';
class Index extends Component {
static childContextTypes = {
store: PropTypes.object
}
getChildContext(){
return { store }
}
render () {
return (
<div>
<Header />
<Content />
</div>
)
}
}
export default Index;
Header.js
获取到store,获取状态中的值
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Header extends Component {
static contextTypes = {
store: PropTypes.object
}
constructor(props){
super(props);
this.state = {
theme: {themeColor: ''}
}
}
componentWillMount(){
const {store} = this.context;
this.updateThemeColor();
store.subscribe(()=>this.updateThemeColor())
}
updateThemeColor = () => {
const {store} = this.context;
const state = store.getState();
this.setState({
themeColor: state.themeColor
})
}
render () {
console.log(this.context)
return (
<h1 style={{ color: this.state.themeColor }}>更换主题色</h1>
)
}
}
export default Header
Content.js
获取context中store的状态值,更新UI,同上类似的逻辑。
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ThemeSwitch from './ThemeSwitch'
class Content extends Component {
render () {
return (
<div>
<p>React.js 小书内容</p>
<ThemeSwitch />
</div>
)
}
}
export default Content
ThemeSwitch.js
调用store.dispatch方法去更新store。
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class ThemeSwitch extends Component {
static contextTypes = {
store: PropTypes.object
}
// dispatch action 去改变颜色
handleSwitchColor (color) {
const { store } = this.context
store.dispatch({
type: 'CHANGE_COLOR',
themeColor: color
})
}
render () {
return (
<div>
<button onClick={()=>this.handleSwitchColor('red')}>Red</button>
<button onClick={()=>this.handleSwitchColor('blue')}>Blue</button>
</div>
)
}
}
export default ThemeSwitch
小结:
如上代码虽然功能点特别简单,但是会发现每个子组件都在写重复的代码,获取context
,通过store
更新数据,更新UI。
而react-redux
中的connect
函数可以让你从上述繁重的工作中解放出来。在了解connect
之前,有必要先了解一下高阶组件。
借助于高阶组件,Header.js
和Content.js
中的获取context
中store
的代码逻辑完全可以复用,你只需要将组件作为参数传入即可。
同时connect
函数还具有将state
转换成props
的能力(mapStateToProps
),自己的组件只需要关注props
获取数据更新UI即可。