我最近在下面的文章State Management with React Hooks — No Redux or Context API中进行游戏。由于从一开始就做出反应,最受关注的问题始终是状态管理和全局状态。 Redux已成为流行的选择,最近成为上下文API。但是这种方法似乎更容易,代码更少,可扩展性更高。
我的问题是,有人能看到使用我可能忽略的这种状态管理方法的弊端吗?我对代码进行了一些调整以支持SSR,它可以在Nextjs中使用,并且使操作和状态变量的设置更加友好。
代码如下:
useGlobalState.js
import React, { useState, useEffect, useLayoutEffect } from 'react';
const effect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
function setState(newState) {
if (newState === this.state) return;
this.state = newState;
this.listeners.forEach((listener) => {
listener(this.state);
});
}
function useCustom() {
const newListener = useState()[1];
effect(() => {
this.listeners.push(newListener);
return () => {
this.listeners = this.listeners.filter((listener) => listener !== newListener);
};
}, []);
return [this.state, this.setState, this.actions];
}
function associateActions(store, actions) {
const associatedActions = {};
if (actions) {
Object.keys(actions).forEach((key) => {
if (typeof actions[key] === 'function') {
associatedActions[key] = actions[key].bind(null, store);
}
if (typeof actions[key] === 'object') {
associatedActions[key] = associateActions(store, actions[key]);
}
});
}
return associatedActions;
}
const useGlobalHook = (initialState, actions) => {
const store = { state: initialState, listeners: [] };
store.setState = setState.bind(store);
store.actions = associateActions(store, actions);
return useCustom.bind(store, React);
};
export default useGlobalHook;
然后为状态变量设置自定义钩子可以是简单的字符串,也可以是一个简单的对象:
import useGlobalState from './useGlobalState';
const initialState = 'Hi';
// Example action for complex processes setState will be passed to component for use as well
const someAction = (store, val) => store.setState(val);
const useValue = useGlobalState(initialState, { someAction });
export default useValue;
并在组件中使用:
import React from 'react'
import useVal from './useVal'
export default () => {
const [val, setVal, actions] = useVal();
const handleClick = () => {
setVal('New Val');
// or use some actions
actions.someAction('New Val');
}
return(
<div>{val}</div>
<button onClick={handleClick}>Click Me</button>
)
}
这一切似乎是一种更清洁,更轻松的方法,我想知道为什么这不是反应状态管理的最佳方法。首先,您不必将所有内容都包装在提供程序中。接下来,它非常容易实现,实际应用中涉及的代码更少。谁能看到使用这种方法的弊端。我唯一能想到的是上下文api的重新渲染问题,但是在小块中这应该不是问题。
答案 0 :(得分:0)
很好的方法,但是对于大型应用程序,尤其是在性能方面,我仍然认为redux
更好。使用您的方法的一个示例是,将按钮添加为单独的组件,同时用React.memo
进行包装,并从按钮组件中触发actions.toggle()
,但是该按钮会重新渲染2次,但不会在更改后继续状态。
因此,在构建大型应用程序时,您总是希望通过删除不必要的重新渲染来提高性能,但这不是这种情况。
这是我的分析,谢谢您的工作。
代码showcase