从另一个中的自定义钩子访问状态

时间:2020-07-02 13:33:36

标签: reactjs typescript

我有一个自定义钩子,可以像这样从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

1 个答案:

答案 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();