【问题标题】:Is it good practice to curry a React hook to follow DRY?使用 React 钩子来遵循 DRY 是一种好习惯吗?
【发布时间】:2021-05-24 18:59:35
【问题描述】:

需要在 React 组件或自定义 React 钩子中调用 React 钩子。它不能在循环内使用。考虑到这一点,请考虑以下情况:

const useListenToStateChange = (state, onEvent, key) => {
    const value = state[key];
    useEffect(() => {
        if (value === null) {
            onEvent(null);
        } else {
            onEvent(key, value);
        }
    }, [value]);
};

const ExampleComponent = (props) => {
    const { context, onError } = props;
    const { state } = useContext(context);
    
    useListenToStateChange(state, onError, KEY_ARRAY[0]);
    useListenToStateChange(state, onError, KEY_ARRAY[1]);
    useListenToStateChange(state, onError, KEY_ARRAY[2]);
    useListenToStateChange(state, onError, KEY_ARRAY[3]);
    useListenToStateChange(state, onError, KEY_ARRAY[4]);
    useListenToStateChange(state, onError, KEY_ARRAY[5]);
    useListenToStateChange(state, onError, KEY_ARRAY[6]);
    useListenToStateChange(state, onError, KEY_ARRAY[7]);
    useListenToStateChange(state, onError, KEY_ARRAY[8]);
    useListenToStateChange(state, onError, KEY_ARRAY[9]);
    
    return <Text>{getTitle(state)}</Text>;
};

ExampleComponent 的返回值并不是重点,所以请忽略它。我担心的是useListenToStateChange被复制粘贴了十次,显然违反了DRY原则。

假设我们需要以这种方式调用useListenToStateChange——我们需要一个监听器来监听useContext返回的state对象的值,它会在发生变化时执行一个带有副作用的函数(即,回调不能在更新state的reducer内部调用;我们需要调用useEffect)。

这就是柯里化的用武之地(注意:我使用lodash/fp 中的currymap):

const useListenToStateChange = _.curry((state, onEvent, key) => {
    const value = state[key];
    useEffect(() => {
        if (value === null) {
            onEvent(null);
        } else {
            onEvent(key, value);
        }
    }, [value]);
});

const ExampleComponent = (props) => {
    const { context, onError } = props;
    const { state } = useContext(context);
    
    const listenToState = useListenToStateChange(state, onError);
    _.map(listenToState, KEY_ARRAY);
    
    return <Text>{getTitle(state)}</Text>;
};

以上代码在 React Native 中有效,运行不报错。

我喜欢它的读取方式,并且我喜欢这种方法使我们能够避免复制粘贴所有键。想象一下,如果您需要基于 KEY_ARRAY 数组设置多个侦听器。那将是一场噩梦。乍一看,我们也是这样遵循钩子规则的:useListenToStateChange 是一个返回 JavaScript 函数的钩子,我们在 React 组件中调用该钩子。

但我正在思考的“问题”是,当你对一个函数进行 curry 时,显然它还没有执行。您必须提供最后一个参数才能运行。这意味着listenToState 在技术上是一个 React 钩子:当你调用它时,它将执行 useListenToStateChange 内部的 useEffect 钩子。

但是,它的名称不像钩子,因此绕过了 React 中的检查,即您必须在顶层调用它。这意味着您可以映射KEY_ARRAY,并且由于它是一个预定义的非动态数组,因此可以保证在每次渲染时都以相同的顺序调用挂钩。因此,它避免了React docs 中列出的问题。

所以我的问题是:这种使用柯里化 React 钩子的做法是否违反了钩子的规则?换句话说,这种模式是好的做法吗?

【问题讨论】:

    标签: reactjs react-native react-hooks standards currying


    【解决方案1】:

    这种对 React 钩子的柯里化的使用是否违反了钩子的规则?

    没有。可以使用柯里化。

    这种模式是好的做法吗?

    我觉得没问题。

    但是,我不建议从外部使用状态。您可以在该函数中使用状态:

    const useListenToStateChange = (onEvent, key) => {
      const { state } = useContext(YourContext);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-06
      • 2013-03-30
      • 2015-09-02
      • 2014-11-05
      • 1970-01-01
      • 2015-02-18
      • 2016-03-20
      相关资源
      最近更新 更多