首页 > 解决方案 > 使用 if 语句中的反应钩子更新多个状态的更好方法?

问题描述

我正在制作一个简单的应用程序,用户可以增加或减少成人、儿童和婴儿的数量。

我想将这些状态作为一种对象形式在一个状态中进行管理,如下所示。

  const [numberState, setNumberState] = useState({
    adultCount: 0,
    childCount: 0,
    babyCount: 0
  });

下面的代码是用户可以增加或减少成人、儿童和婴儿数量的部分。

            <div className="tit">Number</div>
                <dl>
                    <dt><span>Adult</span></dt>
                        <dd>
                            <div className="number_count">
                                <button type="button" className="btn_minus" onClick={() => handleNumberState("adult", "minus")}>minus</button>
                                <span className="input-num"><input type="number" value={adultCount} /></span>
                                <button type="button" className="btn_plus" onClick={() => handleNumberState("adult", "plus")}>plus</button>
                            </div>
                        </dd>
                    <dt><span>Child</span></dt>
                        <dd>
                            <div className="number_count">
                                <button type="button" className="btn_minus" onClick={() => handleNumberState("child", "minus")}>minus</button>
                                <span className="input-num"><input type="number" value={childCount} /></span>
                                <button type="button" className="btn_plus" onClick={() => handleNumberState("child", "plus")}>plus</button>
                            </div>
                        </dd>
                    <dt><span>Baby</span></dt>
                        <dd>
                            <div className="number_count">
                                <button type="button" className="btn_minus" onClick={() => handleNumberState("baby", "minus")}>minus</button>
                                <span className="input-num"><input type="number" value={babyCount} /></span>
                                <button type="button" className="btn_plus" onClick={() => handleNumberState("baby", "plus")}>plus</button>
                            </div>
                        </dd>
                    </dl>
                </div>

正如您所看到的,当用户单击按钮时,它会将两个参数传递给handleNumberState回调函数。

然后函数如下所示。

const handleNumberState = useCallback((gen, state) => {
  if (gen === "adult" && state === "minus" && numberState.adultCount > 0) {
    setNumberState(prevState => {
      return {
        adultCount: prevState.adultCount - 1,
        childCount: prevState.childCount,
        babyCount: prevState.babyCount
      }
    }) 
  }
  if (gen === "adult" && state === "plus") {
    setNumberState(prevState => {
      return {
        adultCount: prevState.adultCount + 1,
        childCount: prevState.childCount,
        babyCount: prevState.babyCount
      }
    }) 
  }
  if (gen === "child" && state === "minus" && numberState.childCount > 0) {
    setNumberState(prevState => {
      return {
        adultCount: prevState.adultCount,
        childCount: prevState.childCount - 1,
        babyCount: prevState.babyCount
      }
    }) 
  }
  if (gen === "child" && state === "plus") {
    setNumberState(prevState => {
      return {
        adultCount: prevState.adultCount,
        childCount: prevState.childCount + 1,
        babyCount: prevState.babyCount
      }
    }) 
  }
  if (gen === "baby" && state === "minus" && numberState.babyCount > 0) {
    setNumberState(prevState => {
      return {
        adultCount: prevState.adultCount,
        childCount: prevState.childCount,
        babyCount: prevState.babyCount - 1
      }
    }) 
  }
  if (gen === "baby" && state === "plus") {
    setNumberState(prevState => {
      return {
        adultCount: prevState.adultCount,
        childCount: prevState.childCount,
        babyCount: prevState.babyCount + 1
      }
    }) 
  }
})

取决于传递给函数的参数,状态在 if 语句中发生变化。

但是代码看起来很乱。

有没有更好的方法可以使用 less if 语句来完成这项工作?

标签: javascriptreactjs

解决方案


更新处理程序以取而代之的是字段和值。

const handleNumberState = (field, value) => {
  setNumberState(prevState => ({
    ...prevState,
    [field]: Math.max(0, prevState[field] + value),
  }))
}

传递要添加到处理程序的字段名称和值。

<div className="tit">Number</div>
<dl>
  <dt>
    <span>Adult</span>
  </dt>
  <dd>
    <div className="number_count">
      <button
        type="button"
        className="btn_minus"
        onClick={() => handleNumberState("adultCount", -1)}
      >
        minus
      </button>
      <span className="input-num">
        <input type="number" value={adultCount} />
      </span>
      <button
        type="button"
        className="btn_plus"
        onClick={() => handleNumberState("adultCount", 1)}
      >
        plus
      </button>
    </div>
  </dd>
  <dt>
    <span>Child</span>
  </dt>
  <dd>
    <div className="number_count">
      <button
        type="button"
        className="btn_minus"
        onClick={() => handleNumberState("childCount", -1)}
      >
        minus
      </button>
      <span className="input-num">
        <input type="number" value={childCount} />
      </span>
      <button
        type="button"
        className="btn_plus"
        onClick={() => handleNumberState("childCount", 1)}
      >
        plus
      </button>
    </div>
  </dd>
  <dt>
    <span>Baby</span>
  </dt>
  <dd>
    <div className="number_count">
      <button
        type="button"
        className="btn_minus"
        onClick={() => handleNumberState("babyCount", -1)}
      >
        minus
      </button>
      <span className="input-num">
        <input type="number" value={babyCount} />
      </span>
      <button
        type="button"
        className="btn_plus"
        onClick={() => handleNumberState("babyCount", 1)}
      >
        plus
      </button>
    </div>
  </dd>
</dl>

编辑更好的更新方式-使用-react-hook-inside-if-statement

一个小的优化是创建一个 curried 处理程序,它使用一个值并返回一个使用 click 事件的回调函数

const handleNumberState = value => e => {
  e.preventDefault();
  const { name } = e.target;
  setNumberState((prevState) => ({
    ...prevState,
    [name]: Math.max(0, prevState[name] + value)
  }));
};

给每个按钮一个name属性,该属性与单击事件一起传递,例如

<button
  name="adultCount"
  type="button"
  className="btn_minus"
  onClick={handleNumberState(-1)}
>
  minus
</button>
<span className="input-num">
  <input type="number" value={adultCount} />
</span>
<button
name="adultCount"
  type="button"
  className="btn_plus"
  onClick={handleNumberState(1)}
>
  plus
</button>

推荐阅读