如何根据预加载数据的 checked/unchecked 输入设置不同的状态
How to set different states based on checked/unchecked inputs with pre-loaded data
我有两组数据来自 API、accountContacts 和 callReportContacts,如下所示:
const accountContacts = [
{
Id: "3SLS-003QZ",
"First Name": "Lynne",
"Last Name": "Froisland"
},
{
Id: "3SLS-003QA",
"First Name": "John",
"Last Name": "Doe"
},
{
Id: "3SLS-003QB",
"First Name": "Jane",
"Last Name": "Doe"
},
{
Id: "3SLS-003RL",
"First Name": "Curtis",
"Last Name": "Shrestha"
},
{
Id: "3SLS-003S1",
"First Name": "Susan",
"Last Name": "Simoncelli"
}
];
const callReportContacts = [
{
Id: "3SLS-003RL",
"First Name": "Curtis",
"Last Name": "Shrestha",
checked: true
},
{
Id: "3SLS-003S1",
"First Name": "Susan",
"Last Name": "Simoncelli",
checked: true
}
];
现在,callReportContacts 默认没有 checked 属性。因此,我在设置状态之前将其添加到响应中。然后我将它们合并,以便 callReportContacts 中的项目替换 accountContacts 中的项目,如下所示:
useEffect(() => {
setMergedContacts(
accountContacts.map((contact) => {
const item = callReportContacts.find(({ Id }) => Id === contact.Id);
return item ? item : contact;
})
);
}, []);
然后我使用输入复选框组件呈现 mergedContacts,如果其设置为 true,则具有预先检查的状态,如下所示:
{mergedContacts.map(({ Id, 'First Name': firstName, 'Last Name': lastName, checked }) => {
return (
<ToggleOption
contacts={contacts}
setContacts={setContacts}
deselectedContacts={deselectedContacts}
setDeselectedContacts={setDeselectedContacts}
key={Id}
contactID={Id}
label={firstName + ' ' + lastName}
ischecked={checked}
/>
)
})
}
我想要的是两组状态,联系人和取消选择的联系人,它们将分别发布到各自的 API 端点。如果我 check/uncheck 一个未检查的输入,它应该是来自联系人状态的 added/removed 并且对于取消选择的联系人状态的预检查输入也是如此。这是 bare bones working link
在示例中,如果我 check/uncheck Lynne、John 或 Jane 他们应该 added/removed 来自联系人状态,如果我对 Curtis 或 Susan 做同样的事情,他们应该 added/removed 来自取消选择的联系人状态。
您可以利用 checked: true
来自 API 的数据。您已经将此数据存储在 mergedContacts
上 - 因此如果最初检查了此对象,您可以将其用作标志。这将在稍后使用,用于评估是否推送到 contacts
或 deselectedContacts
.
话虽如此,我查看了您的 ToggleOption
组件,看起来您已经将该对象属性作为名为 ischecked
的 prop 传递了,此外,您没有进行变异它 - 让工作更轻松。
我所做的是将额外的道具传递给 ToggleOption
组件、deselectedContacts
状态和 setDeselectedContacts
状态 setter。之后,在 ToggleOption
输入的 onChange/onClick 事件中,我传递了 ischecked
属性,它会指示联系人是否最初被检查过。
return (
<div className="toggle-option">
<div onClick={() => handleToggle(ischecked)}>
<input
ref={toggleRef}
data-id={contactID}
onChange={() => handleToggle(ischecked)}
...
最后,在 handleToggle
处理程序上,我根据最初是否检查了联系人,对需要更新的状态设置了条件,再次 - 我使用了 ischecked
属性.
const handleToggle = (ischecked) => {
setCheckedState((prevState) => !checkedState);
const item = {
Id: toggleRef.current.getAttribute("data-id")
};
if (ischecked) {
if (deselectedContacts.map((e) => e["Id"]).includes(item["Id"])) {
setDeselectedContacts(
deselectedContacts.filter((e) => e["Id"] !== item["Id"])
);
} else {
setDeselectedContacts([...deselectedContacts, item]);
}
} else {
if (contacts.map((e) => e["Id"]).includes(item["Id"])) {
setContacts(contacts.filter((e) => e["Id"] !== item["Id"]));
} else {
setContacts([...contacts, item]);
}
}
};
代码沙盒:https://codesandbox.io/s/charming-brown-6rczt?file=/src/App.js
我有两组数据来自 API、accountContacts 和 callReportContacts,如下所示:
const accountContacts = [
{
Id: "3SLS-003QZ",
"First Name": "Lynne",
"Last Name": "Froisland"
},
{
Id: "3SLS-003QA",
"First Name": "John",
"Last Name": "Doe"
},
{
Id: "3SLS-003QB",
"First Name": "Jane",
"Last Name": "Doe"
},
{
Id: "3SLS-003RL",
"First Name": "Curtis",
"Last Name": "Shrestha"
},
{
Id: "3SLS-003S1",
"First Name": "Susan",
"Last Name": "Simoncelli"
}
];
const callReportContacts = [
{
Id: "3SLS-003RL",
"First Name": "Curtis",
"Last Name": "Shrestha",
checked: true
},
{
Id: "3SLS-003S1",
"First Name": "Susan",
"Last Name": "Simoncelli",
checked: true
}
];
现在,callReportContacts 默认没有 checked 属性。因此,我在设置状态之前将其添加到响应中。然后我将它们合并,以便 callReportContacts 中的项目替换 accountContacts 中的项目,如下所示:
useEffect(() => {
setMergedContacts(
accountContacts.map((contact) => {
const item = callReportContacts.find(({ Id }) => Id === contact.Id);
return item ? item : contact;
})
);
}, []);
然后我使用输入复选框组件呈现 mergedContacts,如果其设置为 true,则具有预先检查的状态,如下所示:
{mergedContacts.map(({ Id, 'First Name': firstName, 'Last Name': lastName, checked }) => {
return (
<ToggleOption
contacts={contacts}
setContacts={setContacts}
deselectedContacts={deselectedContacts}
setDeselectedContacts={setDeselectedContacts}
key={Id}
contactID={Id}
label={firstName + ' ' + lastName}
ischecked={checked}
/>
)
})
}
我想要的是两组状态,联系人和取消选择的联系人,它们将分别发布到各自的 API 端点。如果我 check/uncheck 一个未检查的输入,它应该是来自联系人状态的 added/removed 并且对于取消选择的联系人状态的预检查输入也是如此。这是 bare bones working link
在示例中,如果我 check/uncheck Lynne、John 或 Jane 他们应该 added/removed 来自联系人状态,如果我对 Curtis 或 Susan 做同样的事情,他们应该 added/removed 来自取消选择的联系人状态。
您可以利用 checked: true
来自 API 的数据。您已经将此数据存储在 mergedContacts
上 - 因此如果最初检查了此对象,您可以将其用作标志。这将在稍后使用,用于评估是否推送到 contacts
或 deselectedContacts
.
话虽如此,我查看了您的 ToggleOption
组件,看起来您已经将该对象属性作为名为 ischecked
的 prop 传递了,此外,您没有进行变异它 - 让工作更轻松。
我所做的是将额外的道具传递给 ToggleOption
组件、deselectedContacts
状态和 setDeselectedContacts
状态 setter。之后,在 ToggleOption
输入的 onChange/onClick 事件中,我传递了 ischecked
属性,它会指示联系人是否最初被检查过。
return (
<div className="toggle-option">
<div onClick={() => handleToggle(ischecked)}>
<input
ref={toggleRef}
data-id={contactID}
onChange={() => handleToggle(ischecked)}
...
最后,在 handleToggle
处理程序上,我根据最初是否检查了联系人,对需要更新的状态设置了条件,再次 - 我使用了 ischecked
属性.
const handleToggle = (ischecked) => {
setCheckedState((prevState) => !checkedState);
const item = {
Id: toggleRef.current.getAttribute("data-id")
};
if (ischecked) {
if (deselectedContacts.map((e) => e["Id"]).includes(item["Id"])) {
setDeselectedContacts(
deselectedContacts.filter((e) => e["Id"] !== item["Id"])
);
} else {
setDeselectedContacts([...deselectedContacts, item]);
}
} else {
if (contacts.map((e) => e["Id"]).includes(item["Id"])) {
setContacts(contacts.filter((e) => e["Id"] !== item["Id"]));
} else {
setContacts([...contacts, item]);
}
}
};
代码沙盒:https://codesandbox.io/s/charming-brown-6rczt?file=/src/App.js