#reactjs #use-state
#reactjs #use-state
Вопрос:
У меня есть два набора данных, поступающих из API, accountContacts amp; 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, используя компонент input checkbox с предварительно проверенным состоянием, если для него установлено значение 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}
/>
)
})
}
Что я хочу, так это два набора состояний, contacts amp; deselectedContacts, которые будут отправлены в соответствующие конечные точки API отдельно. Если я проверяю / снимаю флажок с непроверенного ввода, он должен быть добавлен / удален из состояния contacts и то же самое для предварительно проверенного ввода для состояния deselectedContacts. Вот рабочая ссылка на голые кости
В примере, если я отмечу / сниму галочку с Линн, Джона или Джейн, они должны быть добавлены / удалены из состояния контактов, и если я сделаю то же самое для Кертиса или Сьюзан, они должны быть добавлены / удалены из состояния отмененных контактов.
Ответ №1:
Вы можете воспользоваться checked: true
данными, поступающими из API. Эти данные вы уже храните на mergedContacts
— так что вы можете использовать их в качестве флага, если этот объект изначально отмечен. Это будет использовано позже, при оценке того, следует ли переходить к contacts
или deselectedContacts
.
С учетом сказанного я взглянул на ваш ToggleOption
компонент, и похоже, что вы уже передаете этот атрибут объекта как prop с именем ischecked
, и, более того, вы не изменяете его, что упрощает работу.
Что я сделал, так это передал дополнительные реквизиты ToggleOption
компоненту, deselectedContacts
состоянию и setDeselectedContacts
установщику состояния. После этого, в событиях onChange / onClick ToggleOption
входных данных, я передал по 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]);
}
}
};
CodeSandbox:https://codesandbox.io/s/charming-brown-6rczt?file=/src/App.js