我正在尝试创建一个可以根据道具激活/禁用某些功能的组件。所有这些功能都需要一个必须进行管理的状态。
我试图考虑一个可能的模式,该模式将允许我们在所连接的功能未激活的情况下不创建状态。我想了两种可能的方法:
方法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 (...);
}
在两种方式下,钩子都能正常工作。问题是:您觉得哪种方式更正确?有更好的方法吗?
答案 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 (...);
}
当自定义钩子中的计算非常昂贵时,这可能尤其重要。