Как можно перезаписать объекты с одинаковым ключом при обновлении состояния с помощью хуков состояния - PullRequest
0 голосов
/ 18 февраля 2020

Я хочу обновить состояние при выборе новых фильтров. начальное состояние показывает структуру объекта, к которому я стремлюсь. например, я добавляю выбор фильтра (например, «f2»), метка фиксируется для каждого фильтра, поэтому мы можем пренебречь им, но значение может быть «va». Это прекрасно работает, но когда я хочу изменить значение для "f2" на "vb", у меня теперь есть две записи в моем состоянии {"f2": "va"} и {"f2": "vb"}, в то время как Я бы предпочел, чтобы первый был перезаписан вторым.

 const [filterValues, setFilterValues] = useState([{"f1":["l","v"]}]);

 const handleChange = (filter, label, value) => {
   setFilterValues([
     ...filterValues,
     {[filter]: [label, value]}
   ]);
 };

Я дважды попытался вызвать setFilterValues ​​(один раз с отображением записей в моем состоянии), чтобы решить проблему, но затем я даже не обновил состояние:

 const handleChange = (filter, label, value) => {
    setFilterValues([
      ...filterValues,
      {[filter]: [label, value]}
    ]);
    let key = filter
    setFilterValues(
      filterValues.map(
        el => el.key == key?  { [key]: [label, value] } : el
      )
    )
  };

я немного нового, чтобы реагировать, так что, возможно, я не получаю фундаментальную вещь с обновлением состояния в функциональных компонентах. Кто-нибудь может мне помочь с этим? спасибо!

Ответы [ 3 ]

0 голосов
/ 18 февраля 2020

Хранение пар меток-значений массива фильтра по ключу в объекте (т. Е. В «карте» или «словаре»), а не в массиве, позволяет осуществлять поиск по ключу в постоянном времени (O (1)), чтобы обновить значение фильтр по ключу ( копирует и возвращает новое значение состояния OF C все еще O (n) ).

Кроме того, используйте обновление функционального состояния для правильного доступа к предыдущему состоянию и очереди обновления состояния.

const [filterValues, setFilterValues] = useState({ f1: ["l","v"] });

const handleChange = (filter, label, value) => {
  setFilterValues(prevFilterValues => ({
    ...prevFilterValues,  // copy previous state
    [filter]: [label, value], // set the value for filter key
  }));
};

Пример:

handleChange('f1', 'l1', 'v1');
// filterValues = { f1: ["l1", "v1"] }

handleChange('f2', 'l2', 'v2');
// filterValues = {
//   f1: ["l1", "v1"],
//   f2: ["l2", "v2"],
// }

handleChange('f1', 'l3', 'v3');
// filterValues = {
//   f1: ["l3", "v3"],
//   f2: ["l2", "v2"],
// }

Демонстрация:

//const [filterValues, setFilterValues] = useState({ f1: ["l","v"] });

// Manual mock for useState return values
let filterValues = { f1: ["l","v"] };
setFilterValues = stateUpdater => filterValues = stateUpdater(filterValues);

const handleChange = (filter, label, value) => {
  setFilterValues(prevFilterValues => ({
    ...prevFilterValues,  // copy previous state
    [filter]: [label, value], // set the value for filter key
  }));
};

// Start Demo
console.log('initial filterValues', filterValues); // { f1: ["l", "v"] }

handleChange('f1', 'l1', 'v1');
console.log('filterValues', filterValues); // { f1: ["l1", "v1"] }

handleChange('f2', 'l2', 'v2');
console.log('filterValues', filterValues); // { f1: ["l1", "v1"], f2: ["l2", "v2"] }

handleChange('f1', 'l3', 'v3');
console.log('filterValues', filterValues); // { f1: ["l3", "v3"], f2: ["l2", "v2"] }
0 голосов
/ 18 февраля 2020
const handleChange = (filter, label, value) => {
    filterValues.map(el => {
      for (let keys in el) {
        if (keys === filter) {
          el[filter] = [label, value];
          setFilterValues([el]);
        } else {
          let newObj = { [filter]: [label, value] };
          let finalArr = [...filterValues, newObj];
          setFilterValues(finalArr);
        }
      }
    });
  };
0 голосов
/ 18 февраля 2020

Способ сделать это - найти нужный объект и изменить его значение перед установкой состояния:

const handleChange = (filter, label, value) => {
   const currentFilters = [...filterValues] // A new copy of the state.
   const newFilters = currentFilters.map(stateFilter => stateFilter[filter] ? {[filter]: [label, value]} : stateFilter)
   setFilterValues(newFilters);
 };

Хотя я считаю, что это решает ваш случай, я думаю, было бы лучше, если бы вы сохранили свой фильтры в массиве, означающие структуру объекта:

[[l1,v1], [l1, v2]]

Таким образом, первый фильтр - это просто индекс 0 в вашем массиве фильтров и так далее. Таким образом, чтобы сделать то, что вы хотите, у вас будет функция, которая получает номер фильтра, метку и значение:

const handleChange = (filter, label, value) => {
   let newFilters = [...filterValues] // A new copy of the state.
   newFilters[filter - 1] = [label, value];
   setFilterValues(newFilters);
 };

Обратите внимание, что если вы получаете номер фильтра 1, то есть первый фильтр, вы хотите чтобы получить доступ к месту 0 в массиве фильтров.

...