1.redux 介绍
- redux api
createStore
createStore(reducer, [preloadedState], enhancer)
combineReducers
rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
applyMiddleware:配合thunk
import thunk from 'redux-thunk'
store = createStore(reducer, applyMiddleware(thunk))
bindActionCreators
bindActionCreators(actionCreators, dispatch)
compose:从右到左来组合多个函数
compose(...functions)
- react-redux api Provider
<Provider store={store}></Provider>
connect
//`options` 设置了 `{ withRef: true }` 才返回被包装的组件实例
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
- redux-thunk :支持 dispatch function,以此让 action creator 控制反转。被 dispatch 的 function 会接收 [
dispatch]作为参数,并且可以异步调用它
2.react-redux 用法
创建store
import { createStore } from 'redux';
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// API 是 { subscribe, dispatch, getState }。
let store = createStore(counter);
store.subscribe(() =>
console.log(store.getState())
);
store.dispatch({ type: 'INCREMENT' }); // 1
store.dispatch({ type: 'INCREMENT' }); // 2
store.dispatch({ type: 'DECREMENT' }); // 1
Provider 全局引入store
import { Provider } from 'react-redux'
const App = ()=>{
<Provider store={store}>
<RouterPage />
</Provider>
)
connect 获取store数据
function addTodo(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text])
default:
return state
}
}
import { bindActionCreators } from 'redux'
function mapStateToProps(state) {
return { todos: state.todos }
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ addTodo }, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
3.响应式原理
store可以订阅状态值,状态变化触发connect 函数 的 store.subscribe订阅函数。
connect通过hoc将store的值通过props传给包裹组件,通过setState触发视图更新。
4.react-redux Provider connect源码
Provider
function createContext(defaultValue, calculateChangedBits) {
var context = {
$$typeof: REACT_CONTEXT_TYPE,
_calculateChangedBits: calculateChangedBits,
_currentValue: defaultValue, //Provider的value属性
_currentValue2: defaultValue,
_threadCount: 0,
Provider: null, //提供组件
Consumer: null //应用组件
};
//context.Provider的_context指向context对象
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context
};
var Consumer = {
$$typeof: REACT_CONTEXT_TYPE,
_context: context,
_calculateChangedBits: context._calculateChangedBits
};
context.Consumer = Consumer; // 这样能拿到<Provider>提供的最新值
//返回一个context对象
return context;
}
connect
var connect = (mapStatetoProps,mapActionstoProps)=>(WrapperComponent)=>{
return class Connect extends Component {
static contextType = storeContext; // provide定义的context对象
constructor(props){
super();
}
componentWillMount(){
const store = this.context;
store.subscribe(this._updateProps)
this._updateProps() // 初始化
}
_updateProps= ()=> {
const store = this.context;
// 传入state和props
var stateProps = mapStatetoProps ? mapStatetoProps(store.getState(),this.props) : {};
// 传入dispatch和props
var actionProps = mapActionstoProps ?mapActionstoProps(store.dispatch,this.props) : {};
//整合props,传给接收的组件
this.setState({
allProps:{
...stateProps,
...actionProps,
...this.props
}
})
}
render() {
return (
<div className="Mid">
<WrapperComponent {...this.state.allProps}/>
</div>
);
}
}
}
5.applyMiddleware 源码
用法:
store = createStore(reducer, applyMiddleware(mid1, mid2, mid3, ...))
等同于
store = applyMiddleware(mid1, mid2, mid3, ...)(createStore)(reducer, null);
applyMiddleware源码:
import compose from './compose';
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, initalState) => {
let store = createStore(reducer, initalState);
let dispatch = store.dispatch;
let chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map( middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch); //f1(f2(f3(store.dispatch)))
return {
...store,
dispatch
};
}
}
function compose(...funs) {
return arg => funcs.reduceRight( (composed, cur) => cur(composed), arg)
}
- logger middleware的源码实现:
export default (store) => next => action => { //store=middlewareAPI
console.log('dispatch:', action);
next(action);
// f3(store.dispatch)->f2(f3(store.dispatch))->f1(f2(f3(store.dispatch)))
console.log('finish:', action);
}
- redux-thunk 异步action
import thunkMiddleware from 'redux-thunk'
const store = createStore(reducer, applyMiddleware(thunkMiddleware))
const login = (userName) => (dispatch,getState) => {
dispatch({ type: 'loginStart' })
request.post('/api/login', { data: userName }, () => {
dispatch({ type: 'loginSuccess', payload: userName })
})
}
store.dispatch(login('Lucy'))
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
参考 www.freesion.com/article/582…
欢迎关注我的前端自检清单,我和你一起成长