文件保存时重新渲染

huangapple go评论53阅读模式
英文:

file rerendering on save

问题

以下是您提供的代码的翻译部分,代码部分不被翻译:

import React, { useEffect, useState } from "react";
import styled from "styled-components";
import arcade from "../assets/images/icon-arcade.svg";
import advanced from "../assets/images/icon-advanced.svg";
import pro from "../assets/images/icon-pro.svg";

const SelectYourPlan = () => {
  const [toggle, setToggle] = useState(0);
  const [init, setInit] = useState(true);
  useEffect(() => {
    console.log(toggle);
    console.log(init);
    if (toggle === 0) {
      document.getElementsByClassName("ball")[0].style.marginLeft = "0vw";
      document.getElementById("left").style.color = "hsl(213, 96%, 18%)";
      document.getElementById("right").style.color = "hsl(231, 11%, 63%)";

      if (init === false) {
        let arcade = document.getElementsByClassName("arcade")[0];
        let advanced = document.getElementsByClassName("advanced")[0];
        let pro = document.getElementsByClassName("pro")[0];

        let arcadePrice = document.getElementById("arcadePrice");
        let advancedPrice = document.getElementById("advancedPrice");
        let proPrice = document.getElementById("proPrice");

        arcadePrice.textContent = "$9/month";
        advancedPrice.textContent = "$12/month";
        proPrice.textContent = "$15/month";

        arcade.removeChild(arcade.lastElementChild);
        advanced.removeChild(advanced.lastElementChild);
        pro.removeChild(pro.lastElementChild);
      }
    } else {
      let extraContentElement = document.createElement("p");
      extraContentElement.textContent = "2 months free";

      let arcade = document.getElementsByClassName("arcade")[0];
      let advanced = document.getElementsByClassName("advanced")[0];
      let pro = document.getElementsByClassName("pro")[0];

      let arcadePrice = document.getElementById("arcadePrice");
      let advancedPrice = document.getElementById("advancedPrice");
      let proPrice = document.getElementById("proPrice");

      arcadePrice.textContent = "$90/year";
      advancedPrice.textContent = "$120/year";
      proPrice.textContent = "$150/year";

      arcade.appendChild(extraContentElement.cloneNode(true));
      advanced.appendChild(extraContentElement.cloneNode(true));
      pro.appendChild(extraContentElement.cloneNode(true));

      arcade.lastElementChild.id = "arcade-free";
      advanced.lastElementChild.id = "advanced-free";
      pro.lastElementChild.id = "pro-free";

      document.getElementsByClassName("ball")[0].style.marginLeft = "1vw";
      document.getElementById("right").style.color = "hsl(213, 96%, 18%)";
      document.getElementById("left").style.color = "hsl(231, 11%, 63%)";
    }
  }, [toggle]);
  const handleClick = () => {
    if (toggle === 0) {
      setToggle(1);
      setInit(false);
    } else {
      setToggle(0);
    }
  };
  return (
    <Container>
      <h1> Select your plan</h1>
      <Subtitle>You have the option of monthly or yearly billing.</Subtitle>
      <Flex>
        <Arcade imgUrl={arcade} className="arcade">
          <Title>Arcade</Title> <Price id="arcadePrice">$9/mo</Price>
        </Arcade>
        <Advanced imgUrl={advanced} className="advanced">
          <Title>Advanced</Title>
          <Price id="advancedPrice">$12/mo</Price>
        </Advanced>
        <Pro imgUrl={pro} className="pro">
          <Title>Pro</Title>
          <Price id="proPrice">$15/mo</Price>
        </Pro>
      </Flex>
      <SwitchBar>
        <Left id="left">Monthly</Left>
        <Switch onClick={handleClick}>
          <Ball className="ball"></Ball>
        </Switch>
        <Right id="right">Yearly</Right>
      </SwitchBar>
      <GoBack>Go Back</GoBack>
      <Next>Next Step</Next>
    </Container>
  );
};

关于您的问题,每次您保存文件时,组件会重新渲染,因此导致额外的语句不断添加。为了解决这个问题,您可以使用 useEffect 钩子来清除先前的额外语句,以确保只有一个额外语句被添加。在 useEffect 中,您可以添加逻辑,检查是否已经存在额外语句,如果存在,则先将其删除,然后再添加新的额外语句。这样可以确保只有一个额外语句存在。

英文:
import React, { useEffect, useState } from &quot;react&quot;;
import styled from &quot;styled-components&quot;;
import arcade from &quot;../assets/images/icon-arcade.svg&quot;;
import advanced from &quot;../assets/images/icon-advanced.svg&quot;;
import pro from &quot;../assets/images/icon-pro.svg&quot;;
const SelectYourPlan = () =&gt; {
const [toggle, setToggle] = useState(0);
const [init, setInit] = useState(true);
useEffect(() =&gt; {
console.log(toggle);
console.log(init);
if (toggle === 0) {
document.getElementsByClassName(&quot;ball&quot;)[0].style.marginLeft = &quot;0vw&quot;;
document.getElementById(&quot;left&quot;).style.color = &quot;hsl(213, 96%, 18%)&quot;;
document.getElementById(&quot;right&quot;).style.color = &quot;hsl(231, 11%, 63%)&quot;;
if (init === false) {
let arcade = document.getElementsByClassName(&quot;arcade&quot;)[0];
let advanced = document.getElementsByClassName(&quot;advanced&quot;)[0];
let pro = document.getElementsByClassName(&quot;pro&quot;)[0];
let arcadePrice = document.getElementById(&quot;arcadePrice&quot;);
let advancedPrice = document.getElementById(&quot;advancedPrice&quot;);
let proPrice = document.getElementById(&quot;proPrice&quot;);
arcadePrice.textContent = &quot;$9/month&quot;;
advancedPrice.textContent = &quot;$12/month&quot;;
proPrice.textContent = &quot;$15/month&quot;;
arcade.removeChild(arcade.lastElementChild);
advanced.removeChild(advanced.lastElementChild);
pro.removeChild(pro.lastElementChild);
}
} else {
let extraContentElement = document.createElement(&quot;p&quot;);
extraContentElement.textContent = &quot;2 months free&quot;;
let arcade = document.getElementsByClassName(&quot;arcade&quot;)[0];
let advanced = document.getElementsByClassName(&quot;advanced&quot;)[0];
let pro = document.getElementsByClassName(&quot;pro&quot;)[0];
let arcadePrice = document.getElementById(&quot;arcadePrice&quot;);
let advancedPrice = document.getElementById(&quot;advancedPrice&quot;);
let proPrice = document.getElementById(&quot;proPrice&quot;);
arcadePrice.textContent = &quot;$90/year&quot;;
advancedPrice.textContent = &quot;$120/year&quot;;
proPrice.textContent = &quot;$150/year&quot;;
arcade.appendChild(extraContentElement.cloneNode(true));
advanced.appendChild(extraContentElement.cloneNode(true));
pro.appendChild(extraContentElement.cloneNode(true));
arcade.lastElementChild.id = &quot;arcade-free&quot;;
advanced.lastElementChild.id = &quot;advanced-free&quot;;
pro.lastElementChild.id = &quot;pro-free&quot;;
document.getElementsByClassName(&quot;ball&quot;)[0].style.marginLeft = &quot;1vw&quot;;
document.getElementById(&quot;right&quot;).style.color = &quot;hsl(213, 96%, 18%)&quot;;
document.getElementById(&quot;left&quot;).style.color = &quot;hsl(231, 11%, 63%)&quot;;
}
}, [toggle]);
const handleClick = () =&gt; {
if (toggle === 0) {
setToggle(1);
setInit(false);
} else {
setToggle(0);
}
};
return (
&lt;Container&gt;
&lt;h1&gt; Select your plan&lt;/h1&gt;
&lt;Subtitle&gt;You have the option of monthly or yearly billing.&lt;/Subtitle&gt;
&lt;Flex&gt;
&lt;Arcade imgUrl={arcade} className=&quot;arcade&quot;&gt;
&lt;Title&gt;Arcade&lt;/Title&gt; &lt;Price id=&quot;arcadePrice&quot;&gt;$9/mo&lt;/Price&gt;
&lt;/Arcade&gt;
&lt;Advanced imgUrl={advanced} className=&quot;advanced&quot;&gt;
&lt;Title&gt;Advanced&lt;/Title&gt;
&lt;Price id=&quot;advancedPrice&quot;&gt;$12/mo&lt;/Price&gt;
&lt;/Advanced&gt;
&lt;Pro imgUrl={pro} className=&quot;pro&quot;&gt;
&lt;Title&gt;Pro&lt;/Title&gt;
&lt;Price id=&quot;proPrice&quot;&gt;$15/mo&lt;/Price&gt;
&lt;/Pro&gt;
&lt;/Flex&gt;
&lt;SwitchBar&gt;
&lt;Left id=&quot;left&quot;&gt;Monthly&lt;/Left&gt;
&lt;Switch onClick={handleClick}&gt;
&lt;Ball className=&quot;ball&quot;&gt;&lt;/Ball&gt;
&lt;/Switch&gt;
&lt;Right id=&quot;right&quot;&gt;Yearly&lt;/Right&gt;
&lt;/SwitchBar&gt;
&lt;GoBack&gt;Go Back&lt;/GoBack&gt;
&lt;Next&gt;Next Step&lt;/Next&gt;
&lt;/Container&gt;
);
};

Actually I have a toggle switch whenever I click on that (when toggle state becomes 1) I want a extra sentence to display at the last in each of 'arcade','advanced','pro' components. This works fine but when I make some changes and save the file on the same toggle position (toggle=1) the statements keep on adding. If I do this on toggle=0 they start to get deleted as per the code. Maybe this is because the page re-renders on saving but is there any way to stop this as this poses great problem in debugging.

答案1

得分: 2

你似乎完全误解了React的使用方式。您不应该使用idclass或任何getElementsByClassNamegetElementByIdstyletextContentremoveChildcreateElementcloneNode等。

相反,您应该根据当前状态返回不同的内容,让React处理DOM操作。以下是您代码的清理版本。
请注意,我们只是根据showYearly是true还是false返回不同的东西。
我将toggle重命名为showYearly以增加清晰度,并删除了init,因为我不知道它的用途。

import React, { useEffect, useState } from "react";
import styled from "styled-components";
import arcade from "../assets/images/icon-arcade.svg";
import advanced from "../assets/images/icon-advanced.svg";
import pro from "../assets/images/icon-pro.svg";

const SelectYourPlan = () => {
  const [showYearly, setShowYearly] = useState(false);
  const handleClick = () => {
    setShowYearly(showYearly => !showYearly);
  };
  return (
    <Container>
      <h1>选择您的计划</h1>
      <Subtitle>您可以选择按月或按年计费</Subtitle>
      <Flex>
        <Arcade imgUrl={arcade}>
          <Title>Arcade</Title>
          <Price>{showYearly ? "$90/year" : "$9/mo"}</Price>
          {showYearly && <p>2个月免费</p>}
        </Arcade>
        <Advanced imgUrl={advanced}>
          <Title>Advanced</Title>
          <Price>{showYearly ? "$120/year" : "$12/mo"}</Price>
          {showYearly && <p>2个月免费</p>}
        </Advanced>
        <Pro imgUrl={pro}>
          <Title>Pro</Title>
          <Price>{showYearly ? "$150/year" : "$15/mo"}</Price>
          {showYearly && <p>2个月免费</p>}
        </Pro>
      </Flex>
      <SwitchBar>
        <Left $showYearly={showYearly}>每月</Left>
        <Switch onClick={handleClick}>
          <Ball $showYearly={showYearly}/>
        </Switch>
        <Right $showYearly={showYearly}>每年</Right>
      </SwitchBar>
      <GoBack>返回</GoBack>
      <Next>下一步</Next>
    </Container>
  );
};

对于LeftRightBall的样式,您应该使用styled-components中的临时属性。例如:

const Left = styled.div`
  color: ${props => props.$showYearly ? "hsl(213, 96%, 18%)" : "hsl(231, 11%, 63%)"};
  [...]
`;
英文:

You seem to completely misunderstand the way React is meant to be used. You should not use id, class, or any of getElementsByClassName, getElementById, style, textContent, removeChild, createElement, cloneNode, etc.

Instead you should simply return something different depending on the current state and let React deal with DOM manipulation. Here is a cleaned up version of your code.
Note that we're simply returning different things depending on whether showYearly is true or false.
I renamed toggle to showYearly for clarity and removed init as I have no idea what it's meant to do.

import React, { useEffect, useState } from &quot;react&quot;;
import styled from &quot;styled-components&quot;;
import arcade from &quot;../assets/images/icon-arcade.svg&quot;;
import advanced from &quot;../assets/images/icon-advanced.svg&quot;;
import pro from &quot;../assets/images/icon-pro.svg&quot;;

const SelectYourPlan = () =&gt; {
  const [showYearly, setShowYearly] = useState(false);
  const handleClick = () =&gt; {
    setShowYearly(showYearly =&gt; !showYearly);
  };
  return (
    &lt;Container&gt;
      &lt;h1&gt; Select your plan&lt;/h1&gt;
      &lt;Subtitle&gt;You have the option of monthly or yearly billing.&lt;/Subtitle&gt;
      &lt;Flex&gt;
        &lt;Arcade imgUrl={arcade}&gt;
          &lt;Title&gt;Arcade&lt;/Title&gt;
          &lt;Price&gt;{showYearly ? &quot;$90/year&quot; : &quot;$9/mo&quot;}&lt;/Price&gt;
          {showYearly &amp;&amp; &lt;p&gt;2 months free&lt;/p&gt;}
        &lt;/Arcade&gt;
        &lt;Advanced imgUrl={advanced}&gt;
          &lt;Title&gt;Advanced&lt;/Title&gt;
          &lt;Price&gt;{showYearly ? &quot;$120/year&quot; : &quot;$12/mo&quot;}&lt;/Price&gt;
          {showYearly &amp;&amp; &lt;p&gt;2 months free&lt;/p&gt;}
        &lt;/Advanced&gt;
        &lt;Pro imgUrl={pro}&gt;
          &lt;Title&gt;Pro&lt;/Title&gt;
          &lt;Price&gt;{showYearly ? &quot;$150/year&quot; : &quot;$15/mo&quot;}&lt;/Price&gt;
          {showYearly &amp;&amp; &lt;p&gt;2 months free&lt;/p&gt;}
        &lt;/Pro&gt;
      &lt;/Flex&gt;
      &lt;SwitchBar&gt;
        &lt;Left $showYearly={showYearly}&gt;Monthly&lt;/Left&gt;
        &lt;Switch onClick={handleClick}&gt;
          &lt;Ball $showYearly={showYearly}/&gt;
        &lt;/Switch&gt;
        &lt;Right $showYearly={showYearly}&gt;Yearly&lt;/Right&gt;
      &lt;/SwitchBar&gt;
      &lt;GoBack&gt;Go Back&lt;/GoBack&gt;
      &lt;Next&gt;Next Step&lt;/Next&gt;
    &lt;/Container&gt;
  );
};

For the style on Left, Right and Ball, you should use transient props from styled-components. For instance:

const Left = styled.div`
  color: ${props =&gt; props.$showYearly ? &quot;hsl(213, 96%, 18%)&quot; : &quot;hsl(231, 11%, 63%)&quot;};
  [...]
`;

答案2

得分: 0

你可以使用React的状态管理来跟踪已添加的元素,并根据需要添加或移除元素。

类似以下的示例,根据你的代码进行调整,这只是一个示例:

const [addedElements, setAddedElements] = useState([]);

useEffect(() => {
  if (toggle === 0) {
    document.getElementsByClassName("ball")[0].style.marginLeft = "0vw";
    document.getElementById("left").style.color = "hsl(213, 96%, 18%)";
    document.getElementById("right").style color = "hsl(231, 11%, 63%)";

    if (init === false) {
      let arcade = document.getElementsByClassName("arcade")[0];
      let advanced = document.getElementsByClassName("advanced")[0];
      let pro = document.getElementsByClassName("pro")[0];

      let arcadePrice = document.getElementById("arcadePrice");
      let advancedPrice = document.getElementById("advancedPrice");
      let proPrice = document.getElementById("proPrice");

      arcadePrice.textContent = "$9/month";
      advancedPrice.textContent = "$12/month";
      proPrice.textContent = "$15/month";

      // 只有在之前已经添加的情况下才移除元素
      if (addedElements.includes("arcade-free")) {
        arcade.removeChild(document.getElementById("arcade-free"));
      }
      if (addedElements.includes("advanced-free")) {
        advanced.removeChild(document.getElementById("advanced-free"));
      }
      if (addedElements.includes("pro-free")) {
        pro.removeChild(document.getElementById("pro-free"));
      }
    }
  } else {
    let extraContentElement = document.createElement("p");
    extraContentElement.textContent = "2 months free";

    let arcade = document.getElementsByClassName("arcade")[0];
    let advanced = document.getElementsByClassName("advanced")[0];
    let pro = document.getElementsByClassName("pro")[0];

    let arcadePrice = document.getElementById("arcadePrice");
    let advancedPrice = document.getElementById("advancedPrice");
    let proPrice = document.getElementById("proPrice");

    arcadePrice.textContent = "$90/year";
    advancedPrice.textContent = "$120/year";
    proPrice.textContent = "$150/year";

    // 只有在之前未添加的情况下才添加元素
    if (!addedElements.includes("arcade-free")) {
      arcade.appendChild(extraContentElement.cloneNode(true));
      arcade.lastElementChild.id = "arcade-free";
      setAddedElements(prevAddedElements => [...prevAddedElements, "arcade-free"]);
    }
    if (!addedElements.includes("advanced-free")) {
      advanced.appendChild(extraContentElement.cloneNode(true));
      advanced.lastElementChild.id = "advanced-free";
      setAddedElements(prevAddedElements => [...prevAddedElements, "advanced-free"]);
    }
  }
}

请注意,这只是一个示例,使用React的状态管理通常更好,如下面示例所示。

英文:

You can use React's state management keeping track of added elements and only add/remove as needed when toggle changes.

Something like this as reference, do adapt to your code, this is only an example.

const [addedElements, setAddedElements] = useState([]);
useEffect(() =&gt; {
if (toggle === 0) {
document.getElementsByClassName(&quot;ball&quot;)[0].style.marginLeft = &quot;0vw&quot;;
document.getElementById(&quot;left&quot;).style.color = &quot;hsl(213, 96%, 18%)&quot;;
document.getElementById(&quot;right&quot;).style.color = &quot;hsl(231, 11%, 63%)&quot;;
if (init === false) {
let arcade = document.getElementsByClassName(&quot;arcade&quot;)[0];
let advanced = document.getElementsByClassName(&quot;advanced&quot;)[0];
let pro = document.getElementsByClassName(&quot;pro&quot;)[0];
let arcadePrice = document.getElementById(&quot;arcadePrice&quot;);
let advancedPrice = document.getElementById(&quot;advancedPrice&quot;);
let proPrice = document.getElementById(&quot;proPrice&quot;);
arcadePrice.textContent = &quot;$9/month&quot;;
advancedPrice.textContent = &quot;$12/month&quot;;
proPrice.textContent = &quot;$15/month&quot;;
// Only remove elements if they were added before
if (addedElements.includes(&quot;arcade-free&quot;)) {
arcade.removeChild(document.getElementById(&quot;arcade-free&quot;));
}
if (addedElements.includes(&quot;advanced-free&quot;)) {
advanced.removeChild(document.getElementById(&quot;advanced-free&quot;));
}
if (addedElements.includes(&quot;pro-free&quot;)) {
pro.removeChild(document.getElementById(&quot;pro-free&quot;));
}
}
} else {
let extraContentElement = document.createElement(&quot;p&quot;);
extraContentElement.textContent = &quot;2 months free&quot;;
let arcade = document.getElementsByClassName(&quot;arcade&quot;)[0];
let advanced = document.getElementsByClassName(&quot;advanced&quot;)[0];
let pro = document.getElementsByClassName(&quot;pro&quot;)[0];
let arcadePrice = document.getElementById(&quot;arcadePrice&quot;);
let advancedPrice = document.getElementById(&quot;advancedPrice&quot;);
let proPrice = document.getElementById(&quot;proPrice&quot;);
arcadePrice.textContent = &quot;$90/year&quot;;
advancedPrice.textContent = &quot;$120/year&quot;;
proPrice.textContent = &quot;$150/year&quot;;
// Only add elements if they haven&#39;t been added before
if (!addedElements.includes(&quot;arcade-free&quot;)) {
arcade.appendChild(extraContentElement.cloneNode(true));
arcade.lastElementChild.id = &quot;arcade-free&quot;;
setAddedElements(prevAddedElements =&gt; [...prevAddedElements, &quot;arcade-free&quot;]);
}
if (!addedElements.includes(&quot;advanced-free&quot;)) {
advanced.appendChild(extraContentElement.cloneNode(true));
advanced.lastElementChild.id = &quot;advanced-free&quot;;

Edit: Since this is not how you should be using React, here is an example of how to properly use React state to store the prices and render them

const [prices, setPrices] = useState({
arcade: &quot;$9/month&quot;,
advanced: &quot;$12/month&quot;,
pro: &quot;$15/month&quot;
});
useEffect(() =&gt; {
if (toggle === 1) {
setPrices({
arcade: &quot;$90/year&quot;,
advanced: &quot;$120/year&quot;,
pro: &quot;$150/year&quot;
});
} else {
setPrices({
arcade: &quot;$9/month&quot;,
advanced: &quot;$12/month&quot;,
pro: &quot;$15/month&quot;
});
}
}, [toggle]);
...
&lt;Arcade imgUrl={arcade} className=&quot;arcade&quot;&gt;
&lt;Title&gt;Arcade&lt;/Title&gt;
&lt;Price&gt;{prices.arcade}&lt;/Price&gt;
&lt;/Arcade&gt;
&lt;Advanced imgUrl={advanced} className=&quot;advanced&quot;&gt;
&lt;Title&gt;Advanced&lt;/Title&gt;
&lt;Price&gt;{prices.advanced}&lt;/Price&gt;
&lt;/Advanced&gt;
&lt;Pro imgUrl={pro} className=&quot;pro&quot;&gt;
&lt;Title&gt;Pro&lt;/Title&gt;
&lt;Price&gt;{prices.pro}&lt;/Price&gt;
&lt;/Pro&gt;

huangapple
  • 本文由 发表于 2023年2月18日 18:00:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492538.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定