简体   繁体   English

是什么阻止了这个 function 执行其中的钩子? 反应机制如何使这成为不可能?

[英]What is preventing this function from executing the hooks inside of it? What about react mechanics makes this impossible?

I'm trying to execute a function that executes other functions.我正在尝试执行执行其他功能的 function。 The function itself executes but the functions inside of it do not. function 本身执行,但其内部的功能不执行。 I thought I had a good grasp on React mechanics and it's lifecycle but I guess not.我以为我对 React 机制和它的生命周期有很好的掌握,但我想不是。 I do not understand why react is acting this way.我不明白为什么 react 会这样。 Hoping for guidance/an explanation on the react component lifecycle and what about it that prevents this particular code from working.希望获得有关反应组件生命周期的指导/解释,以及阻止此特定代码工作的原因。

getInfo.jsx获取信息.jsx

import { useState, useEffect } from "react";

export const useGetCompletionData = () => {
  const [sandIsActive, setSandActive] = useState(false);
  const [dragonIsActive, setDragonActive] = useState(false);
  const [splinterIsActive, setSplinterActive] = useState(false);
  const [tigerIsActive, setTigerActive] = useState(false);
  const [reptileIsActive, setReptileActive] = useState(false);
  const [jungleIsActive, setJungleActive] = useState(false);
  const [totalCamo, setTotalCamo] = useState(0);
  const [goldIsActive, setGoldActive] = useState(false);

  const handleSandClick = (event) => {
    // 👇️ toggle isActive state on click
    setSandActive((current) => !current);
    if (sandIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleDragonClick = (event) => {
    // 👇️ toggle isActive state on click
    setDragonActive((current) => !current);
    if (dragonIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleSplinterClick = (event) => {
    // 👇️ toggle isActive state on click
    setSplinterActive((current) => !current);
    if (splinterIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleTigerClick = (event) => {
    // 👇️ toggle isActive state on click
    setTigerActive((current) => !current);
    if (tigerIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleReptileClick = (event) => {
    // 👇️ toggle isActive state on click
    setReptileActive((current) => !current);
    if (reptileIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleJungleClick = (event) => {
    // 👇️ toggle isActive state on click
    setJungleActive((current) => !current);
    if (jungleIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const setAllCamos = (event) => {
    console.log("set all camos start");
    handleSandClick();
    handleDragonClick();
    handleSplinterClick();
    handleTigerClick();
    handleJungleClick();
    console.log("set all camos finished");
  };

  return {
    goldIsActive,
    setGoldActive,
    totalCamo,
    setTotalCamo,
    sandIsActive,
    handleSandClick,
    handleDragonClick,
    dragonIsActive,
    splinterIsActive,
    handleSplinterClick,
    tigerIsActive,
    handleTigerClick,
    handleReptileClick,
    reptileIsActive,
    jungleIsActive,
    handleJungleClick,
    setAllCamos,
  };
};

AR_list.jsx AR_list.jsx

import React from "react";
import CamoList from "../Completion/CamoList";
import { useState } from "react";
import { useGetCompletionData } from "../../hooks/getInfo";

export default function AR_LIST() {
  const [damascusPercent, setDamascusPercent] = useState(0);
  let { setAllCamos } = useGetCompletionData();
  return (
    <>
      <h1>Assault Rifle</h1>
      <div className="gun-grid">
        <div>
          <h1>ASM10</h1>
          <img
            src="https://i.imgur.com/4rk88oj.jpg"
            alt="ASM10"
            onDoubleClick={setAllCamos}
          />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>AK-47</h1>
          <img src="https://i.imgur.com/tiwEg6m.jpg" alt="AK47" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>M16</h1>
          <img src="https://i.imgur.com/xGbpnJb.jpg" alt="M16" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>M4</h1>
          <img src="https://i.imgur.com/LP0kr6K.jpg" alt="M4" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>BK57</h1>
          <img src="https://i.imgur.com/mUp4KH7.jpg" alt="BK57" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>LK24</h1>
          <img src="https://i.imgur.com/3iNpSfh.jpeg" alt="LK24" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>AK117</h1>
          <img
            src="https://zilliongamer.com/uploads/codm/skins/assault/ak117/ak117-munitions-cod-mobile.jpg"
            alt="AK117"
          />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>M13</h1>
          <img
            src="https://zilliongamer.com/uploads/codm/weapons/ar/m13/m13-cod-mobile.jpg"
            alt="M13"
          />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>Kilo 141</h1>
          <img
            src="https://zilliongamer.com/uploads/codm/weapons/ar/kilo-141/kilo-141-call-of-duty-mobile.jpg"
            alt="Kilo 141"
          />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>KN-44</h1>
          <img src="https://i.imgur.com/OzlDWlk.jpg" alt="KN-44" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>Man-O-War</h1>
          <img src="https://i.imgur.com/Y8AYudI.jpg" alt="Man-O-War" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>CR-56 AMAX</h1>
          <img src="https://i.imgur.com/3ZWIfZA.jpg" alt="CR-56 AMAX" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>AS VAL</h1>
          <img src="https://i.imgur.com/6mzUd8F.jpg" alt="AS VAL" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>Swordfish</h1>
          <img src="https://i.imgur.com/pI8GQ6G.jpg" alt="Swordfish" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>HVK-30</h1>
          <img src="https://i.imgur.com/pCJHS2J.jpg" alt="HVK-30" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>Peacekeeper MK2</h1>
          <img src="https://i.imgur.com/joXdWda.jpg" alt="Peacekeeper MK2" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>FR .556</h1>
          <img src="https://i.imgur.com/zn8pshJ.jpg" alt="FR .556" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>Oden</h1>
          <img src="https://i.imgur.com/Iupg5eL.jpg" alt="Oden" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>ICR-1</h1>
          <img src="https://i.imgur.com/aJNh1Kb.jpg" alt="ICR-1" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>HBRa3</h1>
          <img src="https://i.imgur.com/0Imj29v.jpg" alt="HBRa3" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>

        <div>
          <h1>DR-H</h1>
          <img src="https://i.imgur.com/QE8KvoQ.jpg" alt="DR-H" />
          <CamoList
            damascusPercent={damascusPercent}
            setDamascusPercent={setDamascusPercent}
          />
        </div>
      </div>
    </>
  );
}

CamoList.jsx迷彩列表.jsx

import { useState, useEffect, useContext } from "react";
import { FaCheck } from "react-icons/fa";
import React from "react";
import { useGetCompletionData } from "../../hooks/getInfo";
import { damascusProgress } from "../../damascusContext";

export default function CamoList({ damascusPercent, setDamascusPercent }) {
  const {
    goldIsActive,
    setGoldActive,
    totalCamo,
    setTotalCamo,
    sandIsActive,
    handleSandClick,
    handleDragonClick,
    dragonIsActive,
    splinterIsActive,
    handleSplinterClick,
    tigerIsActive,
    handleTigerClick,
    handleReptileClick,
    reptileIsActive,
    jungleIsActive,
    handleJungleClick,
  } = useGetCompletionData();

  let { setCount } = useContext(damascusProgress);

  useEffect(() => {
    if (totalCamo === 6) {
      setGoldActive((current) => !current);
      setDamascusPercent((prev) => prev + 1);
      setTotalCamo((prev) => prev + 1);
      setCount((prev) => prev + 4.8);
      updateFill();
    }

    function updateFill() {
      let number = (damascusPercent / 20) * 100;
      document.documentElement.style.setProperty(
        "--circle-radius",
        `${number}deg`
      );
    }

    updateFill();
  }, [totalCamo]);

  return (
    <div className="collection">
      <p>{damascusPercent}</p>
      <div
        id="sand"
        className={sandIsActive ? "active" : ""}
        onClick={handleSandClick}
      >
        <div className={sandIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">Kill 600 enemies</span>
        </div>
        <FaCheck className={sandIsActive ? "checkmarkSand" : "nocheckmark"} />
      </div>
      <div
        id="dragon"
        className={dragonIsActive ? "active" : ""}
        onClick={handleDragonClick}
      >
        <div className={dragonIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">Kill 50 enemies with hip fire</span>
        </div>
        <FaCheck
          className={dragonIsActive ? "checkmarkDragon" : "nocheckmark"}
        />
      </div>
      <div
        id="splinter"
        className={splinterIsActive ? "active" : ""}
        onClick={handleSplinterClick}
      >
        <div className={splinterIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">Kill 80 enemies at long distance</span>
        </div>
        <FaCheck
          className={splinterIsActive ? "checkmarkSplinter" : "nocheckmark"}
        />
      </div>
      <div
        id="tiger"
        className={tigerIsActive ? "active" : ""}
        onClick={handleTigerClick}
      >
        <div className={tigerIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">
            Kill 125 enemies with 5 attachments equipped
          </span>
        </div>
        <FaCheck className={tigerIsActive ? "checkmarkTiger" : "nocheckmark"} />
      </div>
      <div
        id="jungle"
        className={jungleIsActive ? "active" : ""}
        onClick={handleJungleClick}
      >
        <div className={jungleIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">Kill 100 enemies with head shots</span>
        </div>
        <FaCheck
          className={jungleIsActive ? "checkmarkJungle" : "nocheckmark"}
        />
      </div>
      <div
        id="reptile"
        className={reptileIsActive ? "active" : ""}
        onClick={handleReptileClick}
      >
        <div className={reptileIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">
            Kill 80 enemies with no attachments equipped
          </span>
        </div>
        <FaCheck
          className={reptileIsActive ? "checkmarkReptile" : "nocheckmark"}
        />
      </div>
      <div id="gold" className={goldIsActive ? "gold-active" : ""}>
        <div className={goldIsActive ? "tooltip-hidden" : "tooltip"}>
          <span className="tooltiptext">Unlock all previous camos</span>
        </div>
        <FaCheck className={goldIsActive ? "checkmarkGold" : "nocheckmark"} />
      </div>
      <div id="platinum"></div>
      <div id="demas"></div>
    </div>
  );
}

Link directly to the function in question on CodeSandbox:在 CodeSandbox 上直接链接到有问题的 function:

https://codesandbox.io/s/practical-gates-rr81j0?file=/src/hooks/getInfo.jsx:2112-2357 https://codesandbox.io/s/practical-gates-rr81j0?file=/src/hooks/getInfo.jsx:2112-2357

Context: I'm trying to make it so double clicking on the picture of the gun sets the camo boxes underneath it to "active".背景:我试图让它双击枪的图片将其下方的迷彩框设置为“活动”。 Each hook function for each box works individually, but when called together in a function nothing happens.每个盒子的每个钩子 function 单独工作,但是当在 function 中一起调用时,什么也没有发生。 Both console.log()'s execute, but not the functions in between them.两个 console.log() 都执行,但不是它们之间的函数。 I was under the impression that calling each "handle${Camo}Click" function in a separate function would work fine, but it doesn't.我的印象是,在单独的 function 中调用每个“handle${Camo}Click”function 可以正常工作,但事实并非如此。 I don't know what to search to start figuring out the mechanics of why this happening.我不知道要搜索什么才能开始弄清楚为什么会发生这种情况的机制。 If anyone could point me in the right direction that would be very much appreciated.如果有人能指出我正确的方向,那将不胜感激。

Issue问题

The issue is that you've defined a useGetCompletionData hook with its own state, but use several instances of the hook so each instance has and maintains its own state independently.问题是您已经使用自己的 state 定义了一个useGetCompletionData挂钩,但使用了多个挂钩实例,因此每个实例都拥有并独立维护自己的 state。

The setAllCamos callback the the ASM10 image is calling is from a different instance of the useGetCompletionData hook that it's related CamoList component is using. ASM10 图像正在调用的setAllCamos回调来自与其相关的CamoList组件正在使用的useGetCompletionData挂钩的不同实例。 In other words, when the image is double-clicked it's updating state the Camolist doesn't have access to.换句话说,当双击图像时,它正在更新Camolist无法访问的 state。

Solution解决方案

I suggest creating a CompletionDataProvider component to wrap individual sets of images and CamoList components so they can share and reference the same state.我建议创建一个CompletionDataProvider组件来包装各个图像集和CamoList组件,以便它们可以共享和引用相同的 state。

Example:例子:

getInfo.jsx获取信息.jsx

import { createContext, useContext, useState } from "react";

export const CompletionData = createContext({
  goldIsActive: false,
  setGoldActive: () => {},
  totalCamo: 0,
  setTotalCamo: () => {},
  sandIsActive: false,
  handleSandClick: () => {},
  handleDragonClick: () => {},
  dragonIsActive: false,
  splinterIsActive: false,
  handleSplinterClick: () => {},
  tigerIsActive: false,
  handleTigerClick: () => {},
  handleReptileClick: () => {},
  reptileIsActive: false,
  jungleIsActive: false,
  handleJungleClick: () => {},
  setAllCamos: () => {},
});

const CompletionDataProvider = ({ children }) => {
  const [sandIsActive, setSandActive] = useState(false);
  const [dragonIsActive, setDragonActive] = useState(false);
  const [splinterIsActive, setSplinterActive] = useState(false);
  const [tigerIsActive, setTigerActive] = useState(false);
  const [reptileIsActive, setReptileActive] = useState(false);
  const [jungleIsActive, setJungleActive] = useState(false);
  const [totalCamo, setTotalCamo] = useState(0);
  const [goldIsActive, setGoldActive] = useState(false);

  const handleSandClick = () => {
    // 👇️ toggle isActive state on click
    setSandActive((current) => !current);
    if (sandIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleDragonClick = () => {
    // 👇️ toggle isActive state on click
    setDragonActive((current) => !current);
    if (dragonIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleSplinterClick = () => {
    // 👇️ toggle isActive state on click
    setSplinterActive((current) => !current);
    if (splinterIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleTigerClick = () => {
    // 👇️ toggle isActive state on click
    setTigerActive((current) => !current);
    if (tigerIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleReptileClick = () => {
    // 👇️ toggle isActive state on click
    setReptileActive((current) => !current);
    if (reptileIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const handleJungleClick = () => {
    // 👇️ toggle isActive state on click
    setJungleActive((current) => !current);
    if (jungleIsActive) {
      setTotalCamo((prev) => prev - 1);
    } else {
      setTotalCamo((prev) => prev + 1);
    }
  };

  const setAllCamos = () => {
    handleSandClick();
    handleDragonClick();
    handleSplinterClick();
    handleTigerClick();
    handleJungleClick();
  };

  const value = {
    goldIsActive,
    setGoldActive,
    totalCamo,
    setTotalCamo,
    sandIsActive,
    handleSandClick,
    handleDragonClick,
    dragonIsActive,
    splinterIsActive,
    handleSplinterClick,
    tigerIsActive,
    handleTigerClick,
    handleReptileClick,
    reptileIsActive,
    jungleIsActive,
    handleJungleClick,
    setAllCamos
  };

  return (
    <CompletionData.Provider {...{ value }}>
      {children}
    </CompletionData.Provider>
  );
};

export const useGetCompletionData = () => useContext(CompletionData);

export default CompletionDataProvider;

AR_list.jsx AR_list.jsx

Wrap the image and CamoList component "pairs" in the imported CompletionDataProvider and use CompletionData.Consumer to access the setAllCamos callback for the image click handler.在导入的CompletionDataProvider中包装图像和CamoList组件“对”,并使用CompletionData.Consumer访问图像单击处理程序的setAllCamos回调。

import React from "react";
import CamoList from "../Completion/CamoList";
import { useState } from "react";
import CompletionDataProvider, { CompletionData } from "../../hooks/getInfo";

export default function AR_LIST() {
  const [damascusPercent, setDamascusPercent] = useState(0);

  return (
    <>
      <h1>Assault Rifle</h1>
      <div className="gun-grid">
        <CompletionDataProvider>
          <div>
            <h1>ASM10</h1>
            <CompletionData.Consumer>
              {({ setAllCamos }) => (
                <img
                  src="https://i.imgur.com/4rk88oj.jpg"
                  alt="ASM10"
                  onDoubleClick={setAllCamos}
                />
              )}
            </CompletionData.Consumer>
            <CamoList
              damascusPercent={damascusPercent}
              setDamascusPercent={setDamascusPercent}
            />
          </div>
        </CompletionDataProvider>

        ...
      </div>
    </>
  );
}

编辑what-is-preventing-this-function-from-executing-the-hooks-inside-of-it-what-abo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM