react 中有一个规则是不有条件地调用 hook。 AFAIK React 只关心调用的钩子数量,所以我尝试了这个:
function useMainHook({ isLive }) {
const res = isLive ? useHookA() : useHookB();
return res; // Make sure to return the result
}
如果react只关心调用了多少个hook,那么这应该可以工作。因为总是有 1 个钩子被调用。
上面的钩子定义有效吗?
function useMainHook({ isLive }) { const res = isLive ? useHookA() : useHookB(); return res; // Make sure to return the result }
如果 React 只关心调用了多少个钩子,那么这应该可行。 因为总是有 1 个钩子被调用。
上面的钩子定义有效吗?
我倾向于说不,这不是有效的用法/定义。
此代码可能有效,但仅作为特殊情况,而不是一般规则。这完全取决于
useHookA
和 useHookB
实际执行的操作,而不仅仅是在一个组件/useMainHook
钩子中调用哪些钩子。 ReactTree 中的 All 渲染组件中的 All React 挂钩称为 each 和 every 渲染周期。
考虑以下两个反例:
const useHookA = () => {
React.useEffect(() => {
console.log("A effect 1");
});
React.useEffect(() => {
console.log("A effect 2");
});
};
const useHookB = () => {
React.useEffect(() => {
console.log("B");
});
};
function App() {
const [state, setState] = React.useState(false);
state ? useHookA() : useHookB();
const toggleState = () => setState((b) => !b);
return (
<div className="App">
<button type="button" onClick={toggleState}>
Toggle
</button>
</div>
);
}
const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root" />
const useHookA = () => {
const [stateA, setStateA] = React.useState("a");
React.useEffect(() => {
console.log("A");
});
};
const useHookB = () => {
React.useEffect(() => {
console.log("B");
});
};
function App() {
const [state, setState] = React.useState(false);
state ? useHookA() : useHookB();
const toggleState = () => setState((b) => !b);
return (
<div className="App">
<button type="button" onClick={toggleState}>
Toggle
</button>
</div>
);
}
const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root" />
你的实现违反了 React 的 Hooks 规则。
不要在循环、条件、嵌套函数或
/try
/catch
块。相反,始终在顶部使用 Hooks 在任何早期返回之前,您的 React 函数的级别。你只能 在 React 渲染函数组件时调用 Hooks:finally
- ✅ 在函数组件主体的顶层调用它们。
- ✅ 在自定义 Hook 主体的顶层调用它们。
不支持调用Hooks(以
开头的函数) 任何其他情况,例如:use
- 🔴 不要在条件或循环内调用 Hook。
- 🔴 不要在条件返回语句后调用 Hooks。
- 🔴 不要在事件处理程序中调用 Hooks。
- 🔴不要在类组件中调用Hooks。
- 🔴 不要在传递给 useMemo、useReducer 或 使用效果。
- 🔴 不要在 try/catch/finally 块内调用 Hooks。
您可以重写您的实现,以免违反 React 的 Hooks 规则。
示例:无条件调用所有钩子,然后有条件返回预期结果。
function useMainHook({ isLive }) {
const resA = useHookA();
const resB = useHookB();
return isLive ? resA : resB;
}