编辑-我修复了这个,我的错(当然)React 组件中 useEffect 上的无效钩子调用错误

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

我收到此错误: 解决方法是我需要以不同的方式更改状态 - 我更新玩家和庄家手牌状态的方式是错误的。 未捕获的错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。发生这种情况可能是由于以下原因之一:

  1. 您的 React 和渲染器版本可能不匹配(例如 React DOM)
  2. 你可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本”

我很难理解为什么,因为

useEffect
正在我的反应组件中使用

以下是原子定义:

import { atom } from "jotai";

export const playerHandAtom = atom([]);
export const dealerHandAtom = atom([]);

为了解决这个问题,我已将所有代码合并到一个文件中,但经销商功能将全部位于文件 Dealer.js 中并导入,但即使在同一组件中,我仍然遇到相同的问题。我不确定这是否是 React 问题的重复版本?

import React, { useEffect } from "react";
import { createRoot } from "react-dom/client";
import { useAtom } from "jotai";
import { playerHandAtom, dealerHandAtom } from "./atoms";
import board from "./img/table_with_chips.png";

const BlackJack = () => {
  const [dealerHand, setDealerHand] = useAtom(dealerHandAtom);
  const [playerHand, setPlayerHand] = useAtom(playerHandAtom);

  const deck = [
    ["2", 2],
    ["3", 3],
    ["4", 4],
    ["5", 5],
    ["6", 6],
    ["7", 7],
    ["8", 8],
    ["9", 9],
    ["10", 10],
    ["jack", 10],
    ["queen", 10],
    ["king", 10],
    ["ace", 11],
  ];

  const dealCard = (hand) => {
    const random = Math.floor(Math.random() * deck.length);
    hand.push(deck[random][0]);
  };

  const dealHand = () => {
    const tempPlayHand = [];
    const tempDealHand = [];
    dealCard(tempPlayHand);
    dealCard(tempPlayHand);
    dealCard(tempDealHand);
    dealCard(tempDealHand);
    setPlayerHand(tempPlayHand);
    setDealerHand(tempDealHand);
  };

  useEffect(() => {
    dealHand();
  }, []);

  return (
    <div id="game-container">
      <img id="game-board" alt="Green Blackjack poker table" src={board} />
    </div>
  );
};

我尝试降级我的依赖项,因为它说版本不匹配也可能是问题所在,但这不起作用,我想将其保留在 React 18 或更高版本,因为我正在使用 createRoot。 以下是我当前的依赖项:建议使用 18.2.0,因为它不是最新的,但我仍然遇到相同的错误。

"jotai": "^2.8.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-router-dom": "^6.23.0"

谢谢大家

javascript reactjs react-hooks hook
3个回答
0
投票
const BlackJack = () => {
  const [dealerHand, setDealerHand] = useAtom(dealerHandAtom);
  const [playerHand, setPlayerHand] = useAtom(playerHandAtom);
  
  const dealCard = (hand) => {
    const random = Math.floor(Math.random() * deck.length);
    hand.push(deck[random][0]);
  };

  const dealHand = () => {
    // ❌ don't call useAtom here again
    // ❌ this function already has access to it
    dealCard(playerHand);
    dealCard(playerHand);
    dealCard(dealerHand);
    dealCard(dealerHand);
  };

  useEffect(() => {
    dealHand();
  }, []);

  // ...
};

-1
投票

我会尝试将两个版本固定为“18.2.0”而不使用 ^ 符号,18.3.1 是最近的版本,可能很快就会有一些补丁

"react": "18.2.0",
"react-dom": "18.2.0",

-2
投票

基本上你不能/不应该在其他钩子中调用钩子,这违反了钩子法则 -> React Hook Rules

这是因为它通常会导致无限的重新渲染等。

我一般不熟悉 Atom 或状态管理器,但您能否显示playerHandAtom 和dealerHandAtom 的代码?这样我们就能为您提供更多帮助。

但通常解决方案很可能是重构代码以允许在 useEffect 中使用它。

© www.soinside.com 2019 - 2024. All rights reserved.