揭开redux,react-redux的神秘面纱

25次阅读

共计 3125 个字符,预计需要花费 8 分钟才能阅读完成。

16 年开始使用 react-redux, 迄今也已两年多。这时候再来阅读和读懂 redux/react-redux 源码,虽已没有当初的新鲜感,但依然觉得略有收获。把要点简单写下来,一方面供感兴趣的读者参考,另一方面也是自己做下总结。
redux
react-redux 最核心的内容就是 redux。内带 redux,react-redux 只提供了几个 API 来关联 redux 与 react 的组件以及 react state 的更新。
首先,看下如何使用 redux。redux 老司机可以直接滑动滚轮至下一章。简单来说,redux 有三个概念,action, reducer 和 dispatch。action 和 dispatch 比较好理解:动作指令和提交动作指令方法。而 reducer,个人在字面上没有理解,但抽象层面上可以理解为用来生成 state 的函数。用一个简单案例体现这三个概念:
// action
const INCREMENT = {type: ‘INCREMENT’}

// reducer
function count(state = 0, action) {
switch(action.type) {
case ‘INCREMENT’:
return state + 1
default:
return state
}
}

// dispatch
// 此处开始使用 redux
const store = redux.createStore(count)
console.log(store.getState() ) // 0
store.dispatch(INCREMENT)
console.log(store.getState() ) // 1
接下来说说 redux 中的两大模块:

store 对象
中间件

store 对象
APIcreateStore 会创建了一个 store 对象, 创建的过程中它主要做了下面两件事:

初始化 state
暴露相关接口:getState(), dispatch( action), subscribe(listener) 等。其中 getState() 用来获取 store 中的实时 state, dispatch(action) 根据传入的 action 更新 state, subscribe(listener) 可以监听 state 的变化。

中间件
中间件可以用来 debug 或提交异步动作指令. 在初始化 store 的时候,我们通过 createStore(reducer, state, applyMiddleware( middleware1, middleware2) ) 添加多个中间件。为了实现多个中间件,redux 专门引入了函数式编程的 compose() 方法,简单来说,compose 将多层函数调用的写法变得优雅:
// 未使用 compose 方法
a(b( c( ‘d’) ) )

// 用 compose 方法
compose(a, b, c)(‘d’)
而中间件的写法比较奇特,是多级函数,在阅读源码的时候有点绕。显然中间件的写法还可以优化,尽管现在的写法方便在源码中使用,但对 redux 用户来说稍显复杂,可以用单层函数。
function logMiddleware({getState}) {
return nextDispatch => action => {
console.log(‘before dispatch’, getState() )
const res = nextDispatch(action)
console.log(‘after dispatch’, getState() )
return res
}
}
react-redux
了解了 redux 运作原理,就可以知道 react-redux 的大部分使用场景是如何运作。react-redux 提供了几个 API 将 redux 与 react 相互关联。
基于上一个案例展示 react-redux 的用法:
// action
const increment = () => ({ type: ‘INCREMENT’})

// reducer
function count(state = 0, action) {
switch(action.type) {
case ‘INCREMENT’:
return state + 1
default:
return state
}
}

// redux
const store = Redux.createStore(count)

// react-redux
const {Provider, connect} = ReactRedux
const mapStateToProps = state => ({ count: state} )
const mapDispatchToProps = dispatch => ({ increment : () => dispatch(increment() ) } )
const App = connect(mapStateToProps, mapDispatchToProps)(class extends React.Component {
onClick = () => {
this.props.increment()
}
render() {
return <div>
<p>Count: {this.props.count}</p>
<button onClick={this.onClick}>+</button>
</div>
}
} )

ReactDOM.render(<Provider store={ store}>
<App />
</Provider>, document.getElementById(‘app’) )
点击运行案例
react-redux 提供最常用的两个 API 是:

Provider
connect

Provider
Provider 本质上是一个 react 组件,通过 react 的 context api(使一个组件可以跨多级组件传递 props) 挂载 redux store 中的 state,并且当组件初始化后开始监听 state。当监听到 state 改变,Provider 会重新 setState 在 context 上的 storeState,简要实现代码如下:
class Provider extends Component {
constructor(props) {
super(props)

const {store} = props

this.state = {
storeState: Redux.store.getState(),
}
}

componentDidMount() {
this.subscribe()
}

subscribe() {
const {store} = this.props
store.subscribe(() => {
const newStoreState = store.getState()
this.setState(providerState => {
return {storeState: newStoreState}
})
})
}
render() {
const Context = React.createContext(null)
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
}
}
connect()
connect 方法通过 connectHOC(HOC: react 高阶组件)将部分或所有 state 以及提交动作指令方法赋值给 react 组件的 props。
小结
写 react 不用 redux 就像写代码不用 git, 我们需要用 redux 来更好地管理 react 应用中的 state。了解 redux/react-redux 的运作原理会消除我们在使用 redux 开发时的未知和疑惑,并且在脑中有一个完整的代码执行回路,让开发流程变得透明,直观。
如果本文帮助到了你,我也十分荣幸, 欢迎点赞和收藏。如果有任何疑问或者建议,都欢迎在下方评论区提出。

正文完
 0