javascript - 使用 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 语句来完成这项工作?
解决方案
更新处理程序以取而代之的是字段和值。
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>
一个小的优化是创建一个 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>
推荐阅读
- javascript - SQLSTATE=08001 尝试连接到 db2 远程 db node.js 时出错
- json - 通过 for 循环列出的 json 嵌套值
- python - 为什么在进行 conda 安装或只是运行 anaconda 虚拟环境时出现 ssl 错误?
- azure - 无法查询 Azure WAF 日志
- python - matplotlib 多 Y 轴熊猫图
- c# - 来自 Linq 表达式的 JsonPointer
- python - 从 github 存储库导入 Python 的问题
- parallel-processing - 如何测量处理器中内核之间的流量?
- php - 更新到 PHP 8.1 RC5 后 PHP 无法正常工作
- python - Py2neo 从对象创建节点