像 ComponentDidUpdate 一样使用 useEffect

时间:2020-12-19 05:46:48

标签: javascript reactjs use-effect

我正在尝试使用 3 个按钮,如果其中一个处于活动状态,则其他 2 个将自动处于非活动状态。

 if (isActive === "true") {
            setActive2("false")
            setActive3("false")
          }
          if (isActive2 === "true") {
            setActive("false")
            setActive3("false")
          }
          if (isActive3 === "true") {
            setActive("false")
            setActive2("false")
          }

我知道可能有更好的方法来执行此操作,这是一个蛮力选项,我愿意接受您的建议。
我曾尝试将这段代码放在一个函数中,并在单击按钮时运行它,但这给了我以前的状态而不是当前状态。 所以我被建议使用 useEffect 钩子。

 useEffect(() => {
          
          if (isActive === "true") {
            setActive2("false")
            setActive3("false")
          }
          if (isActive2 === "true") {
            setActive("false")
            setActive3("false")
          }
          if (isActive3 === "true") {
            setActive("false")
            setActive2("false")
          }
}, [isActive, isActive2, isActive3]);

然而,这给了我同样的问题,其中应用了先前的状态。
我肯定这个钩子做错了什么(我以前从未使用过它)。 我有一个代码沙盒,里面有我所有的代码 here

2 个答案:

答案 0 :(得分:1)

仅以有效的方式修改了 onChange handler,而没有过多接触 JSX,并且仅对您的设置进行了处理。 CodeSandBox 链接 Checkbox-Selection

我所做的一些主要变化如下:

  1. 我没有为每个按钮设置单独的状态,而是使用了一个带有 3 个键 isActiveisActive2isActive3 的单个对象。

    const [btnStatus, setBtnStatus] = useState({
     isActive: true,
      isActive2: true,
      isActive3: true
    });
    
  2. 您的处理程序现在看起来像这样。

    const addPizza = (e) => {
     setPizzaSize(e.target.name);
     setStartPrice(parseInt(e.target.value));
    const currentActive = e.target.id;
    
    if (currentActive === "isActive") {
      setBtnStatus({ isActive: true, isActive2: false, isActive3: false });
      console.log("1");
    }
    if (currentActive === "isActive2") {
      setBtnStatus({ isActive: false, isActive2: true, isActive3: false });
      console.log("2");
    }
    if (currentActive === "isActive3") {
      setBtnStatus({ isActive: false, isActive2: false, isActive3: true });
      console.log("3");
    }
    
    console.log(btnStatus);
    };
    
  3. 在您的 JSX 中,每个按钮看起来像这样,带有自己的 ids 来跟踪按钮的状态。

      <button
        name="Extra Large"
        className={
          btnStatus.isActive3
            ? "button btn fourth"
            : "button btn fourthActive"
        }
        value="20"
        onClick={addPizza}
        id="isActive3"
      >
        Extra large
      </button>
    

就这样吧。使用相同的代码可以很好地工作:)

答案 1 :(得分:0)

我已经稍微更新了代码,您可以创建单独的常量并使用它们来减少代码,并且保持活动状态仅使用单个状态。

https://codesandbox.io/s/gracious-franklin-m8wkx?file=/src/CYO.js:0-4147

import React, { useState, useEffect } from "react";
import ButtonClickable from "./button";
import ButtonClickable2 from "./button2";
import { burgerSize, vegToppings, nonvegToppings } from "./const/size";
import "./index.css";

const CYO = () => {
  const [pizzaSize, setPizzaSize] = useState("Choose your Pizza Size");
  const [activeSize, setActiveSize] = useState(burgerSize.MEDIUM);
  const [toppings, setToppings] = useState([]);
  const [startPrice, setStartPrice] = useState(0);
  const addPizza = (e) => {
    setPizzaSize(e.target.name);
    setStartPrice(parseInt(e.target.value));
  };

  const CheckSize = () => {
    if (pizzaSize === "Choose your Pizza Size") {
      alert("You must choose a pizza size");
    } else if (toppings.length === 0) {
      alert("Are you sure you don't want toppings?");
    } else {
      alert("Sorry, this isn't a real pizza place.");
    }
  };
  const ToppingPlusMinus = (e) => {
    const { value } = e.target;
    const position = toppings.indexOf(value);

    if (position !== -1) {
      return removeTopping(value);
    }

    return addTopping(value);
  };

  const removeTopping = (value) => {
    // We need to filter out the value from the array and return the expected new value
    setToppings(toppings.filter((topping) => topping !== value));
    //handleToggle();
  };

  const addTopping = (value) => {
    setToppings([...toppings, value]);
    // handleToggle();
  };

  let toppingPrice = toppings.length * 1.5;
  let price = startPrice + toppingPrice;

  return (
    <div className="container CYO">
      <h2 className="text-center white">Create your own pizza</h2>
      <div className="row">
        <div className="col-sm-8">
          <div className="">
            <img
              src="./pizza.png"
              className="img-fluid pizza"
              alt="Pizza"
            ></img>
          </div>
          <h3 className="white">{pizzaSize}</h3>
          <p className="white">
            Your Toppings: <br />
            <div className="col-lg-12">
              {toppings
                .filter((x) => x.name !== "")
                .map((toppings) => (
                  <img
                    src={toppings}
                    alt="topping"
                    width="100px"
                    height="100px"
                  ></img>
                ))}
            </div>{" "}
          </p>
        </div>
        <div className="col-sm-4">
          <h3 className="white">Pizza size</h3>
          {Object.values(burgerSize).map((value) => (
            <button
              name={value}
              className={
                activeSize !== value
                  ? "button btn fourth"
                  : "button btn fourthActive"
              }
              value="10"
              onClick={(event) => {
                addPizza(event);
                setActiveSize(value);
              }}
            >
              {value}
            </button>
          ))}
          <br />
          <h3 className="white">Toppings</h3>
          <p className="white">Toppings are $1.50 each</p>
          <div className="topping-wrapper">
            <h4 className="white">Meats</h4>
            {nonvegToppings.map(({ name, image }) => (
              <ButtonClickable
                onClick={(event) => {
                  ToppingPlusMinus(event);
                }}
                name={name}
                value={image}
              />
            ))}

            <h4 className="white">Veggies</h4>
            {vegToppings.map(({ name, image }) => (
              <ButtonClickable2
                onClick={(event) => {
                  ToppingPlusMinus(event);
                }}
                name={name}
                value={image}
              />
            ))}
          </div>
        </div>

        <div className="pricefooter">
          <p className="price">Price: ${price}</p>
        </div>
        <div className="pricefooter2">
          <button className="checkout button btn fourth" onClick={CheckSize}>
            Checkout
          </button>
        </div>
      </div>
    </div>
  );
};
export default CYO;