Redux 外围
是js的状态容器 提供可预测化的状态治理
- actions:
- reducers:
- store
应用步骤,以计数器为例
<button id="inc">减少</button><span id="count"></span><button id="dec">缩小</button>
- 创立store对象
var store = Redux.createStore(reducer)
创立reducer函数, 给定默认初始状态,并匹配action
function reducer(state = initState, action) { switch (action.type) { case 'increment': return { ...state, count: state.count + 1 } case 'decrement': return { ...state, count: state.count - 1 } default: return state break }}
定义action
var increment = { type: 'increment' }var decrement = { type: 'decrement' }
触发action
store.dispatch(increment)
订阅store变动,同步视图变动
store.subscribe(() => { console.log(store.getState())})
react-redux
Provider
组件
必须位于想要共享状态的组件的顶层,将组件包裹,用于提供store,全局可用<Provider store={store}> <Children></Provider>
connect
办法- 提供state到指定组件的props映射,同时将store的dispatch办法也放入了props中
- 帮忙咱们订阅store,当store状态产生扭转的时候,从新渲染组件
- 能够通过传递第二个参数,用来简化视图中的dispatch代码
// counter.jsimport React from 'react'import { connect } from 'react-redux'import { increment, decrement } from '../store'const Counter = ({ count, inc, dec}) => { return ( <> <button onClick={inc}>+</button> <span>{count}</span> <button onClick={dec}>-</button> </> )}const mapStateToProps = state => ({ a: '10099', count: state.count})// 映射dispatch 办法const mapDispatchToPrps = dispatch => ({ inc() { dispatch(increment) }, dec() { dispatch(decrement) }})// connect的两个办法, 第一个映射state到props,第二个 映射dispatch到props中,能够缩小视图代码export default connect(mapStateToProps, mapDispatchToPrps)(Counter)
- combineReducer办法
将多个reducer文件拆分后,应用redux提供的combineReduver办法进行合并reducer
Redux 中间件
实质就是一个函数,容许咱们扩大redux应用程序
开发Redux中间件
模板代码
export const middleware = store => next => action { next(action)}
reducer
中,须要应用redux
提供的applyMiddleware
办法。中间件执行的程序就是调用这个办法是,传递过来的程序。执行完了中间件的操作,能力继续执行reducer,
// 模仿实现/** * 中间件函数 * 执行完middlewares, 而后须要返回最后的须要执行的reducer * @param {...any} middlewares * @returns */function applyMiddleware(...middlewares) { // 调用enhancer的时候,传进来的createStore return function(createStore) { // enhancer函数传递过去的reducer, preloadState return function(reducer, preloadState) { // 创立一个store, 将用于返回咱们自定义的增强型的store,实际上中间件只需啊哟对dispatch进行加强后返回 const store = createStore(reducer, preloadState) // 保留新建的store里的函数 const middlewareAPI = { getState: store.getState, dispatch: store.dispatch } // 调用中间件的第一层函数, 执行中间件最外层的函数, 这里须要将传递一个没有disptch的store对象给下一层级应用 let chain = middlewares.map(middleware => middleware(middlewareAPI)) // 将创立的dispatch进行重写, 获取到最初的dispatch, 期待action命令. 依照设计,先注册的先执行. let dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }}
Redux解决异步操作
Redux-thunk
模仿thunk
/** * 解决异步操作 * @param {*} store * @returns */const thunk = ({dispatch}) => next => action => { // 解决异步操作, 异步操作的action须要返回一个函数,这个函数的参数就是dispath if (typeof action === 'function') { return action(dispatch) } // 同步操作不受影响 next(action)}export default thunk
// actions中,// 应用thunk中间件调用这个办法名 须要返回一个接管dispatch的函数,// 通过这个dispatch来接管异步操作的后果,// 而后触发同步的action,同时将值传递过来export const increment_async = payload => dispatch => { setTimeout(() => { dispatch(increment(payload)) }, 2000);}
redux-thunk能够间接应用,
Redux-saga
- 解决异步逻辑
redux-actions
createAction
创立action,不再须要申明字符串等,外部做了获取type,以及payload的操作
export const increment = createAction("increment")export const decrement = createAction("decrement")
如此,便可在reducer中间接应用 signup
也可间接通过 bindActionCreators
包裹后的dispatch间接调用
bindActionCreators
将所有的action保存起来,返回一个蕴含action的对象import React from 'react'import { connect } from 'react-redux'import { bindActionCreators } from "redux"import * as counterActions from '../store/actions/counter.action'const Counter = ({ count, increment, decrement, increment_async}) => { return ( <> <button onClick={() => increment(6)}>+</button> <span>{count}</span> <button onClick={() => decrement(5)}>-</button> </> )}const mapStateToProps = state => ({ count: state.counter.count})const mapDispatchToPrps = dispatch => (bindActionCreators(counterActions, dispatch))export default connect(mapStateToProps, mapDispatchToPrps)(Counter)
handleActions
用于简化reducer的创立import { handleActions as createReducer } from "redux-actions";import { increment, decrement } from "../actions/counter.action";const initState = { count: 0}export default createReducer({ [increment]: (state, action) => ({ count: state.count + action.payload}), [decrement]: (state, action) => ({ count: state.count - action.payload})}, initState)
终极简化 @reduxjs/tooltik
reduxjs官网的工具集
configureStore(): wraps createStore to provide simplified configuration options and good defaults. It can automatically combine your slice reducers, adds whatever Redux middleware you supply, includes redux-thunk by default, and enables use of the Redux DevTools Extension.
createReducer(): that lets you supply a lookup table of action types to case reducer functions, rather than writing switch statements. In addition, it automatically uses the immer library to let you write simpler immutable updates with normal mutative code, like state.todos[3].completed = true.
createAction(): generates an action creator function for the given action type string. The function itself has toString() defined, so that it can be used in place of the type constant.
createSlice(): accepts an object of reducer functions, a slice name, and an initial state value, and automatically generates a slice reducer with corresponding action creators and action types.
createAsyncThunk: accepts an action type string and a function that returns a promise, and generates a thunk that dispatches pending/fulfilled/rejected action types based on that promise
createEntityAdapter: generates a set of reusable reducers and selectors to manage normalized data in the store
The createSelector utility from the Reselect library, re-exported for ease of use.