内容简介:针对 react hooks 的新版本解决方案若想要无缝使用原来的 redux,和其配套的中间件 promise,thunk,saga 等等的话可以使用
针对 react hooks 的新版本解决方案
一.redux维持原方案
若想要无缝使用原来的 redux,和其配套的中间件 promise,thunk,saga 等等的话
可以使用 redux-react-hook
github 链接 redux-react-hook
一个简单的使用例子:
import {useDispatch, useMappedState} from 'redux-react-hook'; export function DeleteButton({index}) { // 类似于以前 react-redux 中的 connect 函数 const mapState = useCallback( state => ({ canDelete: state.todos[index].canDelete, name: state.todos[index].name, }), [index], ); // 获取 redux 的数据 const {canDelete, name} = useMappedState(mapState); // 获取 dispatch const dispatch = useDispatch(); // button click handle const deleteTodo = useCallback( () => dispatch({ type: 'delete todo', index, }), [index], ); return ( <button disabled={!canDelete} onClick={deleteTodo}> Delete {name} </button> ); }
使用方法和以前一致
二.使用 useReducer 与 context
在 index 或 app 中提供全局的 redux 与 dispatch
function isPromise(obj) { return ( !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function" ); } function wrapperDispatch(dispatch) { // 功能和 redux-promise 相同 return function (action) { isPromise(action.payload) ? action.payload.then(v => { dispatch({type: action.type, payload: v}) }).catch((error) => { dispatch(Object.assign({}, action, { payload: error, error: true })); return Promise.reject(error); }) : dispatch(action); }; } function Wrap(props) { // 确保在 dispatch 后不会刷新APP组件 const [state, dispatch] = useReducer(reducers, ReducersValue); console.log('render wrap') return (<MainContext.Provider value={{state: state, dispatch: wrapperDispatch(dispatch)}}>{props.children}</MainContext.Provider>) } function App() { console.log('render App') return <Wrap> <Router> <Switch> <Route path="/login" component={Login} exact/> <Route path="/" component={MainIndex}/> </Switch> </Router> </Wrap> }
具体使用:
function useDispatch() { // 获取 dispatch const store = useContext(MainContext); return store.dispatch; } function useStoreState(mapState) { //存储 state 且判断是否需要 render const {state:store} = useContext(MainContext); const mapStateFn = () => mapState(store); const [mappedState, setMappedState] = useState(() => mapStateFn()); const lastRenderedMappedState = useRef(); // Set the last mapped state after rendering. useEffect(() => { lastRenderedMappedState.current = mappedState; }); useEffect( () => { console.log('useEffect ') const checkForUpdates = () => { const newMappedState = mapStateFn(); if (!_.isEqual(newMappedState, lastRenderedMappedState.current)) { setMappedState(newMappedState); } }; checkForUpdates(); }, [store, mapState], ); return mappedState } // 组件内使用 const ResourceReducer = useStoreState(state => state.ResourceReducer) const dispatch = useDispatch()
他的功能已经足够了,在使用的地方使用函数即可,很方便
但是也有一些不足的地方是在根源上的,即 context,
在同一个页面中 如果有多个使用 context 的地方
那么如果一旦dispatch ,其他的所有地方也会触发render 造成资源的浪费,小项目还好,大项目仍旧不可
取
(除非 react 的 context 函数添加 deps)
三.自定义解决方案
原理就是存储一个全局变量 ,通过 import 引入;
我自己写了一个例子: https://github.com/Grewer/react-hooks-store
想要基础的实现只需要 30+ 行的代码即可
class Modal { private value: any; private prevValue: any; private reducers: (state, action) => {}; private queue: any = []; private dispatch: (action) => void; constructor(reducers) { this.reducers = combineReducers(reducers) // combineReducers 来自于 reudx ,可以引入也可以自己写一个(后续我会写一个库,会包含此函数) this.value = this.reducers({}, {}) this.dispatch = action => { this.prevValue = this.value; this.value = this.reducers(this.value, action) this.onDataChange() } } useModal = (deps?: string[]) => { const [, setState] = useState(this.value); useEffect(() => { const index = this.queue.push({setState, deps}); // 订阅 return () => { // 组件销毁时取消 this.queue.splice(index - 1, 1); }; }, []); return [this.value, this.dispatch] } onDataChange = () => { this.queue.forEach((queue) => { const isRender = queue.deps ? queue.deps.some(dep => this.prevValue[dep] !== this.value[dep]) : true isRender && queue.setState(this.value) }); } }
// 初始化 reducers
const modal = new Modal({ countReducer: function (state = 0, action) { console.log('count Reducer', state, action) switch (action.type) { case "ADD": console.log('trigger') return state + action.payload || 1 default: return state } }, listReducer: function (state = [] as any, action) { console.log('list Reducer', state, action) switch (action.type) { case "ADD_LIST": console.log('trigger') state.push(action.payload) return [...state] default: return state } }, personReducer: function (state = {name: 'lll', age: 18} as any, action) { console.log('person Reducer', state, action) switch (action.type) { case "CHANGE_NAME": return Object.assign({}, state, {name: action.payload}) default: return state } } }) // 导出 useModal export const useModal = modal.useModal
简单的使用:
function Count(props) { const [state, dispatch] = useModal(['countReducer']) // 非 countReducer 的更新 不会触发此函数 render console.warn('render Count', state, dispatch) return <div> <button onClick={() => dispatch({type: "ADD", payload: 2})}>+</button> </div> }
当然你也可以自己写一个,自己想要的方案
总结
hooks 的存储方案基本就这 3 类,可以用现成的,也可以使用自己写的方案
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- QuickDAO4.1.3 发布,优化全局类型转换和新增多字段关联
- 全局变量,静态全局变量,局部变量,静态局部变量
- Thrift RPC 系列教程(2)——全局变量&全局常量
- 全局角度出发讨论敏捷
- 全局事务锁等待分析
- 避免全局变量
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java语言程序设计(基础篇 原书第10版)
[美]粱勇(Y.Daniel Liang) / 戴开宇 / 机械工业出版社 / 2015-7 / 85.00元
《Java语言程序设计(基础篇 原书第10版)》是Java语言的经典教材,中文版分为基础篇和进阶篇,主要介绍程序设计基础、面向对象编程、GUI程序设计、数据结构和算法、高级Java程序设计等内容。本书以示例讲解解决问题的技巧,提供大量的程序清单,每章配有大量复习题和编程练习题,帮助读者掌握编程技术,并应用所学技术解决实际应用开发中遇到的问题。您手中的这本是其中的基础篇,主要介绍了基本程序设计、语法......一起来看看 《Java语言程序设计(基础篇 原书第10版)》 这本书的介绍吧!