Можно ли обновлять только состояние массива объектов?

Мне было интересно, есть ли какая-либо документация или ссылка, которая могла бы помочь мне понять, как обновить состояние массива объектов (без дубликатов).

Мое состояние выглядит так:

accounts: [
    { name: ‘mike’ },
    { name: ‘tee’ },
    { name: ‘ralf’ },
    { name: ‘candy’ },
    { name: ‘bon’ },
    { name: ‘salm’ },
    { name: ‘shark’ },
    { name: ‘tof’ },
    { name: ‘hulk’ },
    { name: ‘zar’ },
    { name: ‘blake’ },
  ],

предстоящий массив выглядит так:

accounts: [
    { name: 'mike’, balance: ’1000’},
    { name: 'tee’, balance: ’235345’},
    { name: 'zar’, balance: ’3455’},
    { name: 'candy’, balance: ’567567’},
    { name: 'tee’, balance: ’8767’},
    { name: 'salm', balance: ’234’},
    { name: 'blake', balance: ’134’},
  ],

Таким образом, обновленное состояние setState будет выглядеть так:

accounts: [
    { name: 'mike’, balance: ’1000’},
    { name: 'tee’, balance: ’235345’},
    { name: ‘ralf’ },
    { name: 'candy’, balance: ’567567’},
    { name: ‘bon’ },
    { name: 'salm', balance: ’234’},
    { name: ‘shark’ },
    { name: ‘tof’ },
    { name: ‘hulk’ },
    { name: 'zar’, balance: ’3455’},
    { name: 'blake', balance: ’134’},
  ],

Я пробовал с prevState.accounts.concat(accounts), но он только добавляет дубликаты.

Если у вашего accounts нет повторяющихся имен, не будет ли логичнее, чтобы это был объект? Тогда это будет намного эффективнее.

Mark 07.04.2019 20:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
74
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Найдите объект на основе условия, а затем обновите значения, где используйте метод Array#find для поиска элемента и метод Object.assign для копирования значений в существующий объект.

accounts.forEach( o => {
   let oldObj = prevState.accounts.find(o1 => o1.name === o.name);
   Object.assign(oldObj, o)
})

Окончательный код будет выглядеть так:

this.setState(prevState => {
  newAccounts.forEach(o => {
    let oldObj = prevState.accounts.find(o1 => o1.name === o.name);
    Object.assign(oldObj, o)
  })
  return prevState.accounts
});

Решение Oneliner путем создания нового массива.

this.setState(prevState => newAccounts.map(o => Object.assign(prevState.accounts.find(o1 => o1.name === o.name), o)));

// if you don't want to mutate original object in previous state then

this.setState(prevState => newAccounts.map(o => Object.assign({}, prevState.accounts.find(o1 => o1.name === o.name), o)));

// or with ES6 spread syntax
this.setState(prevState => newAccounts.map(o => ({ ...prevState.accounts.find(o1 => o1.name === o.name), ...o }))));

Я бы использовал {} в качестве первого аргумента, чтобы сделать его чистым.

Jonas Wilms 07.04.2019 20:16

@JonasWilms: зависит от его потребностей ... {...oldObj, ...o} или Object.assign({}, oldObj, o)

Pranav C Balan 07.04.2019 20:18

Большое спасибо. Это кажется полезным, но как мне использовать этот метод для setState?

mediaroot 07.04.2019 21:01

@mediaroot this.setState(prevState => { newAccounts.forEach(o => { let oldObj = prevState.accounts.find(o1 => o1.name === o.name); Object.assign(oldObj, o) return prevState.accounts }) });

Pranav C Balan 07.04.2019 21:05

Удивительно. Большое спасибо.

mediaroot 07.04.2019 21:12

Если ваши новые учетные записи состояний всегда будут подмножеством значений предыдущих учетных записей состояний. Вы можете использовать что-то вроде этого

this.state = {
    accounts : [
        { name: 'mike' },
        { name: 'tee' },
        { name: 'ralf' },
        { name: 'candy' },
        { name: 'bon' },
        { name: 'salm' },
        { name: 'shark' },
        { name: 'tof' },
        { name: 'hulk' },
        { name: 'zar' },
        { name: 'blake' },
    ]
}
const newAccounts = [
    { name: 'mike', balance: 1000},
    { name: 'tee', balance: 235345},
    { name: 'zar', balance: 3455},
    { name: 'candy', balance: 567567},
    { name: 'tee', balance: 8767},
    { name: 'salm', balance: 234},
    { name: 'blake', balance: 134},
]
this.setState({accounts: this.state.accounts.map (x => ({...x, ...newAccounts.find(y => y.name === x.name)}))});

Вы можете использовать Массив.найти, чтобы найти значения старых учетных записей состояния в новых учетных записях, а затем использовать ... или Объект.назначить для объединения свойств.

Разве это не изменит объекты prevState?

mediaroot 07.04.2019 21:35

Большое спасибо. Да, это всегда будет подмножество

mediaroot 07.04.2019 21:35

нет, это не будет мутировать, потому что .map вернет новый массив, а я использую... для деструктуризации и возврата новых объектов для этого массива

Ashish 07.04.2019 21:37

Другие вопросы по теме