我有一个自定义钩子,可以像这样从DOM中读取和解析JSON对象:
export const useConfig = () => {
const [config, setConfig] = useState<Config>();
useEffect(() => {
if (document) {
const config = document.getElementById('some-dom-element');
setConfig(JSON.parse(config?.innerHTML || '{}'));
}
}, []);
return config;
};
该对象为我的应用程序中的不同问题提供了一些有意义的信息。
因此,我创建了另一个钩子,该钩子仅从配置对象中获取objects
数组:
export const useOptions = () => {
const [options, setOptions] = useState<Options>();
const config = useConfig();
useLayoutEffect(() => {
setOptions(config?.options);
}, [options]);
return options;
};
这没关系,但是如果我只想从DOM中读取一次,则需要在组件树的顶层调用我的useOptions
钩子,并将结果传递给下层,以便使组件进一步下降树可以访问它。
是否可以更改useOptions
钩子,以便仅在需要它的函数组件中调用它,而不必在每次调用时都由useConfig
读取DOM?
编辑:我可能可以将Recoil用作轻量级状态管理解决方案,但是我想知道是否有更好的方法来编写这些钩子,这样我就不需要添加其他deps
答案 0 :(得分:0)
您正在描述充当a singleton的自定义钩子。
尝试使用reusable
library,实现很简单,因此您可以将其用作配方:
const useCounter = createStore(() => {
const [counter, setCounter] = useState(0);
return {
counter,
increment: () => setCounter(prev => prev + 1)
}
});
const Comp1 = () => {
const something = useCounter();
}
const Comp2 = () => {
const something = useCounter(); // same something
}
const App = () => (
<ReusableProvider> {/* no initialization code, stores automatically plug into the top provider */}
...
</ReusableProvider>
)
因此,对于您的用例,useConfig
应该应该位于全局存储中:
const useConfig = {...};
export default createStore(useConfig);
// Always the same config
const config = useConfig();