Как установить различные состояния на основе проверенных / непроверенных входных данных с предварительно загруженными данными

#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