反应挂钩:可激活的状态模式

时间:2019-03-21 10:51:42

标签: reactjs design-patterns react-hooks

我正在尝试创建一个可以根据道具激活/禁用某些功能的组件。所有这些功能都需要一个必须进行管理的状态。

我试图考虑一个可能的模式,该模式将允许我们在所连接的功能未激活的情况下不创建状态。我想了两种可能的方法:

方法1

function useFunctionality(initState, enable) {
    if (!enable) {
        return null;
    }

    const [funct, updateFunct] = useState(init);
    return funct;
}

function Component({ enableFunct }) {
    const funct = useFunctionality('test', enableFunct);
    return (...);
}

方法2

function useFunctionality(initState, enable) {
    const [funct, updateFunct] = useState(init);
    return enable ? funct : null;
}

function Component({ enableFunct }) {
    const funct = useFunctionality('test', enableFunct);
    return (...);
}

在两种方式下,钩子都能正常工作。问题是:您觉得哪种方式更正确?有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

两个食谱都有问题。

方法1可能允许在组件渲染时有条件地调用一个钩子,这可能会导致错误ans是discouraged

  

请勿在循环,条件或嵌套函数中调用Hook。相反,请始终在您的React函数的顶层使用挂钩。通过遵循此规则,可以确保每次渲染组件时都以相同的顺序调用Hook。这就是让React在多个useState和useEffect调用之间正确保留Hook的状态的原因。

this answer中所述,只要可以保证渲染之间的条件不变,就可以放弃此规则。

保证这一点的一种方法是记住一个条件:

function useFunctionality(initState, enable) {
    const condition = useMemo(() => enable, []);

    if (!condition)
        return null;

    const [funct, updateFunct] = useState(initState);
    return funct;
}

方法2更可取,因为它更干净而且useState通话也不昂贵。

两种方式都有相同的问题,它们使用的状态永远不变。如果这是目的,那就是参考的用例。由于它永远不会改变,因此可以将条件作为初始值:

function useFunctionality(initState, enable) {
    return useRef(enable ? initState: null).current;
}

答案 1 :(得分:0)

如果您希望基于prop禁用特定功能的使用,更好的方法是不执行功能,而不是执行整个逻辑并返回null或undefined,因为我们不需要响应。所以第一种方法是更好的方法

function useFunctionality(initState, enable) {
    if (!enable) {
        return null;
    }

    const [funct, updateFunct] = useState(init);
    return funct;
}

function Component({ enableFunct }) {
    const funct = useFunctionality('test', enableFunct);
    return (...);
}

当自定义钩子中的计算非常昂贵时,这可能尤其重要。