我正在尝试创建一个可以根据道具激活/禁用某些功能的组件。所有这些功能将需要必须管理的状态。
我试图考虑一种可能的模式,以使我们不创建状态,以防连接功能不活跃。我想到了两种可能的方法:
方式#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 (...);
}
在这两种方面,钩子都在继续工作。问题是:哪种方式更正确?有更好的方法?
两个配方都有问题。
方法1可能允许在组件渲染条件下调用钩子,这可能导致错误ANS:
不要在循环,条件或嵌套功能中调用钩子。相反,请务必在您的React功能的顶级使用钩子。通过遵循此规则,您可以确保每次组件渲染时都以相同的顺序调用钩子。这就是允许反应正确保留多个USESTATE和使用效率调用之间的钩子状态的原因。
正如本答案中所述,只要保证条件不会在渲染之间变化。
保证这一点的一种方法是记住条件:
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;
}
如果您想根据道具禁用特定功能,那么更好的方法是不执行功能,而不是执行整个逻辑并返回null或未定义,因为我们没有需要回应。因此,第一种方法是更好的方法
function useFunctionality(initState, enable) {
if (!enable) {
return null;
}
const [funct, updateFunct] = useState(init);
return funct;
}
function Component({ enableFunct }) {
const funct = useFunctionality('test', enableFunct);
return (...);
}
当自定义挂钩内部的计算昂贵时,这可能特别重要。