javascript - 如何在嵌套对象中的值之间切换
问题描述
我有一个名为 useToggles 的 React 钩子,用于我的应用程序中的各种复选框和单选按钮。到目前为止,我已经能够摆脱类似以下的事情:
const useToggles = (initialValues = {}) => {
const [toggleValues, setToggleValues] = useState(initialValues);
const handleToggle = e => {
const name = e.currentTarget.attributes.name.value;
const value = toggleValues[e.currentTarget.attributes.name.value];
setToggleValues(values => ({ ...values, [name]: !value }));
};
return {
toggleValues,
setToggleValues,
handleToggle,
};
};
export default useToggles;
一个示例复选框组件:
<CheckBox
checked={toggleValues.gluten || false}
label="Gluten"
onChange={handleToggle}
name="gluten"
/>
因此,尽管我的“toggleValues”对象以 {} 开头,但只要选中复选框,它就会填充该对象。所以我们可能有:
{
gluten: true,
soy: false
}
因为这个对象只有一层,所以展开值并使用[name]: !value
翻转布尔值将起作用。
然而,当需要更多的组织时,这就会分崩离析。在另一页上,我有几组复选框,我需要将它们的值组合在一起以填充各个数据库字段。为了处理这个问题,我在复选框中添加了一层组织:
<CheckBox
checked={toggleValues.dietType.paleo || ''}
label="Paleo"
onChange={handleToggle}
name="dietType.paleo"
/>
我们在应用程序的其他地方使用了这种组织方法来对数据进行分组,并使用点对象解析字符串。来自你的例子seFormValues()
: dot.str(e.target.name, value, tmp)
;
此方法不起作用,useToggles
因为我们依赖于toggleValues
对象中先前存在的数据。每次单击复选框时,使用 dot-object 始终会创建对象的新层。但是我还没有找到一种使用 [name] 来选择对象的第二级或第三级的方法。
为了可视化这一点,我需要做的是获取这个对象并根据接收名称“dietType.paleo”的函数将paleo的值翻转为true:
{
dietType: {
paleo: true;
},
intolerances: {}
}
解决方案
您可以使用 currying 并将复选框组名称作为参数传递给handleToggle
:
const handleToggle = sub => e => {
const name = e.currentTarget.attributes.name.value;
if (!sub) setToggleValues({ ...toggleValues, [name]: !toggleValues[name] });
else {
const newSub = { ...toggleValues[sub], [name]: !toggleValues[sub][name] };
setToggleValues({ ...toggleValues, [sub]: newSub });
}
};
现在onChange={handleToggle()}
用于顶层和onChange={handleToggle("dietType")}
古复选框。
编辑:
另一种方法是检查其中是否name
有句点并相应地分支:
const handleToggle = e => {
const name = e.currentTarget.attributes.name.value;
if (!~name.indexOf("."))
setToggleValues({ ...toggleValues, [name]: !toggleValues[name] });
else {
const [sub, prop] = name.split(".");
const newSub = { ...toggleValues[sub], [prop]: !toggleValues[sub][prop] };
setToggleValues({ ...toggleValues, [sub]: newSub });
}
};
这样你就可以保持现有的 JSX 1:1。
推荐阅读
- python - KMeans 聚类多维特征
- php - 通过 CSV 复制记录更新数据库
- android - 使用自定义布局在动作模式中包装标题文本
- typo3 - 在 Typo3 中为 Mask-Elements 设置后端标题
- elixir - 迁移数据库约束
- python - 在循环网络上使用预训练的句子嵌入
- symfony - 教义 find() 和 querybuilder() 在 PHPUnit 测试中返回不同的结果
- android-studio - Flutter build.gradle 麻烦
- jdbc - 无法使用 Java JDBC 从 AWS EMR 上的 Presto 连接/查询
- javascript - 已声明标识符 - 已声明标识符“userScore”