在react中有条件地调用钩子

问题描述 投票:0回答:1

react 中有一个规则是不有条件地调用 hook。 AFAIK React 只关心调用的钩子数量,所以我尝试了这个:

function useMainHook({ isLive }) {
  const res = isLive ? useHookA() : useHookB();
  return res;  // Make sure to return the result
}

如果react只关心调用了多少个hook,那么这应该可以工作。因为总是有 1 个钩子被调用。

上面的钩子定义有效吗?

react-hooks
1个回答
0
投票
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
/
finally
块。相反,始终在顶部使用 Hooks 在任何早期返回之前,您的 React 函数的级别。你只能 在 React 渲染函数组件时调用 Hooks:

  • ✅ 在函数组件主体的顶层调用它们。
  • ✅ 在自定义 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.